| Directory: | ./ |
|---|---|
| File: | storage/innobase/handler/ha_innodb.cc |
| Date: | 2022-11-26 14:12:44 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 8306 | 9541 | 87.1% |
| Branches: | 7914 | 13395 | 59.1% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /***************************************************************************** | ||
| 2 | |||
| 3 | Copyright (c) 2000, 2022, Oracle and/or its affiliates. | ||
| 4 | Copyright (c) 2008, 2009 Google Inc. | ||
| 5 | Copyright (c) 2009, Percona Inc. | ||
| 6 | Copyright (c) 2012, Facebook Inc. | ||
| 7 | |||
| 8 | Portions of this file contain modifications contributed and copyrighted by | ||
| 9 | Google, Inc. Those modifications are gratefully acknowledged and are described | ||
| 10 | briefly in the InnoDB documentation. The contributions by Google are | ||
| 11 | incorporated with their permission, and subject to the conditions contained in | ||
| 12 | the file COPYING.Google. | ||
| 13 | |||
| 14 | Portions of this file contain modifications contributed and copyrighted | ||
| 15 | by Percona Inc.. Those modifications are | ||
| 16 | gratefully acknowledged and are described briefly in the InnoDB | ||
| 17 | documentation. The contributions by Percona Inc. are incorporated with | ||
| 18 | their permission, and subject to the conditions contained in the file | ||
| 19 | COPYING.Percona. | ||
| 20 | |||
| 21 | This program is free software; you can redistribute it and/or modify it under | ||
| 22 | the terms of the GNU General Public License, version 2.0, as published by the | ||
| 23 | Free Software Foundation. | ||
| 24 | |||
| 25 | This program is also distributed with certain software (including but not | ||
| 26 | limited to OpenSSL) that is licensed under separate terms, as designated in a | ||
| 27 | particular file or component or in included license documentation. The authors | ||
| 28 | of MySQL hereby grant you an additional permission to link the program and | ||
| 29 | your derivative works with the separately licensed software that they have | ||
| 30 | included with MySQL. | ||
| 31 | |||
| 32 | This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 33 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 34 | FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, | ||
| 35 | for more details. | ||
| 36 | |||
| 37 | You should have received a copy of the GNU General Public License along with | ||
| 38 | this program; if not, write to the Free Software Foundation, Inc., | ||
| 39 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 40 | |||
| 41 | *****************************************************************************/ | ||
| 42 | |||
| 43 | /** @file ha_innodb.cc */ | ||
| 44 | |||
| 45 | #ifndef UNIV_HOTBACKUP | ||
| 46 | #include "my_config.h" | ||
| 47 | #endif /* !UNIV_HOTBACKUP */ | ||
| 48 | |||
| 49 | #include <auto_thd.h> | ||
| 50 | #include <errno.h> | ||
| 51 | #include <fcntl.h> | ||
| 52 | #include <gstream.h> | ||
| 53 | #include <limits.h> | ||
| 54 | #include <log.h> | ||
| 55 | #include <math.h> | ||
| 56 | #include <my_compare.h> | ||
| 57 | #include <mysqld.h> | ||
| 58 | #include <stdlib.h> | ||
| 59 | #include <strfunc.h> | ||
| 60 | #include <time.h> | ||
| 61 | |||
| 62 | #include <algorithm> | ||
| 63 | |||
| 64 | #include <sql_table.h> | ||
| 65 | #include "mysql/components/services/system_variable_source.h" | ||
| 66 | |||
| 67 | #ifndef UNIV_HOTBACKUP | ||
| 68 | #include <current_thd.h> | ||
| 69 | #include <debug_sync.h> | ||
| 70 | #include <derror.h> | ||
| 71 | #include <my_bitmap.h> | ||
| 72 | #include <my_check_opt.h> | ||
| 73 | #include <mysql/service_thd_alloc.h> | ||
| 74 | #include <mysql/service_thd_wait.h> | ||
| 75 | #include <mysql_com.h> | ||
| 76 | #include <sql_acl.h> | ||
| 77 | #include <sql_class.h> | ||
| 78 | #include <sql_show.h> | ||
| 79 | #include <sql_tablespace.h> | ||
| 80 | #include <sql_thd_internal_api.h> | ||
| 81 | #include <sys_vars_shared.h> | ||
| 82 | #include "api0api.h" | ||
| 83 | #include "api0misc.h" | ||
| 84 | #include "arch0arch.h" | ||
| 85 | #include "arch0page.h" | ||
| 86 | #include "auth_acls.h" | ||
| 87 | #include "btr0btr.h" | ||
| 88 | #include "btr0cur.h" | ||
| 89 | #include "btr0sea.h" | ||
| 90 | #include "buf0dblwr.h" | ||
| 91 | #include "buf0dump.h" | ||
| 92 | #include "buf0flu.h" | ||
| 93 | #include "buf0lru.h" | ||
| 94 | #include "buf0stats.h" | ||
| 95 | #include "clone0api.h" | ||
| 96 | #include "clone0clone.h" | ||
| 97 | #include "dd/dd.h" | ||
| 98 | #include "dd/dictionary.h" | ||
| 99 | #include "dd/impl/bootstrap/bootstrap_ctx.h" | ||
| 100 | #include "dd/properties.h" | ||
| 101 | #include "dd/types/index.h" | ||
| 102 | #include "dd/types/object_table.h" | ||
| 103 | #include "dd/types/object_table_definition.h" | ||
| 104 | #include "dd/types/partition.h" | ||
| 105 | #include "dd/types/table.h" | ||
| 106 | #include "dd/types/tablespace.h" | ||
| 107 | #include "ddl0ddl.h" | ||
| 108 | #include "dict0boot.h" | ||
| 109 | #include "dict0crea.h" | ||
| 110 | #include "dict0dd.h" | ||
| 111 | #include "dict0dict.h" | ||
| 112 | #include "dict0load.h" | ||
| 113 | #include "dict0stats.h" | ||
| 114 | #include "dict0stats_bg.h" | ||
| 115 | #include "fil0crypt.h" | ||
| 116 | #include "fil0fil.h" | ||
| 117 | #include "fsp0fsp.h" | ||
| 118 | #include "fsp0space.h" | ||
| 119 | #include "fsp0sysspace.h" | ||
| 120 | #include "fts0fts.h" | ||
| 121 | #include "fts0plugin.h" | ||
| 122 | #include "fts0priv.h" | ||
| 123 | #include "fts0tokenize.h" // true_word_char | ||
| 124 | #include "fts0types.h" | ||
| 125 | #include "ha_innodb.h" | ||
| 126 | #include "ha_innopart.h" | ||
| 127 | #include "ha_prototypes.h" | ||
| 128 | #include "i_s.h" | ||
| 129 | #include "ibuf0ibuf.h" | ||
| 130 | #include "lex_string.h" | ||
| 131 | #include "lob0lob.h" | ||
| 132 | #include "lock0lock.h" | ||
| 133 | #include "log0buf.h" | ||
| 134 | #include "log0chkp.h" | ||
| 135 | #include "log0encryption.h" | ||
| 136 | #include "log0meb.h" | ||
| 137 | #include "log0pfs.h" | ||
| 138 | #include "log0pre_8_0_30.h" | ||
| 139 | #include "log0write.h" | ||
| 140 | #include "mem0mem.h" | ||
| 141 | #include "mtr0mtr.h" | ||
| 142 | #include "my_compare.h" | ||
| 143 | #include "my_compiler.h" | ||
| 144 | #include "my_dbug.h" | ||
| 145 | #include "my_double2ulonglong.h" | ||
| 146 | #include "my_io.h" | ||
| 147 | #include "my_macros.h" | ||
| 148 | #include "my_psi_config.h" | ||
| 149 | #include "mysql/components/services/log_builtins.h" | ||
| 150 | #include "mysql/plugin.h" | ||
| 151 | #include "mysql/psi/mysql_data_lock.h" | ||
| 152 | #include "mysys_err.h" | ||
| 153 | #include "os0thread-create.h" | ||
| 154 | #include "os0thread.h" | ||
| 155 | #include "p_s.h" | ||
| 156 | #include "page0zip.h" | ||
| 157 | #include "pars0pars.h" | ||
| 158 | #include "rem0types.h" | ||
| 159 | #include "row0ext.h" | ||
| 160 | #include "row0import.h" | ||
| 161 | #include "row0ins.h" | ||
| 162 | #include "row0mysql.h" | ||
| 163 | #include "row0quiesce.h" | ||
| 164 | #include "row0sel.h" | ||
| 165 | #include "row0upd.h" | ||
| 166 | #include "sql/plugin_table.h" | ||
| 167 | #include "srv0mon.h" | ||
| 168 | #include "srv0srv.h" | ||
| 169 | #include "srv0start.h" | ||
| 170 | #include "sync0sync.h" | ||
| 171 | #ifdef UNIV_DEBUG | ||
| 172 | #include "trx0purge.h" | ||
| 173 | #endif /* UNIV_DEBUG */ | ||
| 174 | #include "dict0priv.h" | ||
| 175 | #include "dict0sdi.h" | ||
| 176 | #include "dict0upgrade.h" | ||
| 177 | #include "os0thread-create.h" | ||
| 178 | #include "os0thread.h" | ||
| 179 | #include "sql/auth/auth_common.h" | ||
| 180 | #include "sql/item.h" | ||
| 181 | #include "sql_base.h" | ||
| 182 | #include "srv0tmp.h" | ||
| 183 | #include "trx0rec.h" | ||
| 184 | #include "trx0roll.h" | ||
| 185 | #include "trx0rseg.h" | ||
| 186 | #include "trx0sys.h" | ||
| 187 | #include "trx0trx.h" | ||
| 188 | #include "trx0xa.h" | ||
| 189 | #include "ut0mem.h" | ||
| 190 | #include "ut0test.h" | ||
| 191 | #include "xtradb_i_s.h" | ||
| 192 | #else | ||
| 193 | #include <typelib.h> | ||
| 194 | #include "buf0types.h" | ||
| 195 | #include "univ.i" | ||
| 196 | #endif /* !UNIV_HOTBACKUP */ | ||
| 197 | |||
| 198 | #include "log0files_io.h" | ||
| 199 | |||
| 200 | #include "sql-common/json_binary.h" | ||
| 201 | #include "sql-common/json_dom.h" | ||
| 202 | |||
| 203 | #include "os0enc.h" | ||
| 204 | #include "os0file.h" | ||
| 205 | |||
| 206 | #include <mutex> | ||
| 207 | #include <sstream> | ||
| 208 | #include <string> | ||
| 209 | #include <vector> | ||
| 210 | |||
| 211 | #ifdef HAVE_UNISTD_H | ||
| 212 | #include <unistd.h> | ||
| 213 | #endif /* HAVE_UNISTD_H */ | ||
| 214 | |||
| 215 | #ifndef UNIV_HOTBACKUP | ||
| 216 | |||
| 217 | namespace innobase { | ||
| 218 | namespace component_services { | ||
| 219 | SERVICE_TYPE(registry) *reg_srv = nullptr; | ||
| 220 | |||
| 221 | /** Initialize component service handles */ | ||
| 222 | 12027 | static bool intitialize_service_handles() { | |
| 223 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | DBUG_TRACE; |
| 224 | |||
| 225 | ✗ | auto cleanup = [&]() { | |
| 226 | /* Add module specific deinitialization here */ | ||
| 227 | ✗ | innobase::encryption::deinit_keyring_services(reg_srv); | |
| 228 | ✗ | mysql_plugin_registry_release(reg_srv); | |
| 229 | ✗ | }; | |
| 230 | |||
| 231 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | reg_srv = mysql_plugin_registry_acquire(); |
| 232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | if (reg_srv == nullptr) { |
| 233 | ✗ | return false; | |
| 234 | } | ||
| 235 | |||
| 236 | /* Add module specific initialization here */ | ||
| 237 |
2/4✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
|
12027 | if (innobase::encryption::init_keyring_services(reg_srv) == false) { |
| 238 | ✗ | cleanup(); | |
| 239 | ✗ | return false; | |
| 240 | } | ||
| 241 | |||
| 242 | /* During initialize, PFS is not ready. */ | ||
| 243 |
3/4✓ Branch 0 taken 11730 times.
✓ Branch 1 taken 297 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
|
23757 | if (!opt_initialize && |
| 244 |
2/4✓ Branch 0 taken 11730 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11730 times.
|
11730 | !log_pfs_acquire_services(innobase::component_services::reg_srv)) { |
| 245 | ✗ | ib::warn(ER_IB_MSG_LOG_PFS_ACQUIRE_SERVICES_FAILED); | |
| 246 | } | ||
| 247 | |||
| 248 | 12027 | return true; | |
| 249 | 12027 | } | |
| 250 | |||
| 251 | /** Deinitialize compoent service handles */ | ||
| 252 | 10504 | static void deinitialize_service_handles() { | |
| 253 |
1/2✓ Branch 0 taken 10504 times.
✗ Branch 1 not taken.
|
10504 | DBUG_TRACE; |
| 254 |
2/2✓ Branch 0 taken 10204 times.
✓ Branch 1 taken 300 times.
|
10504 | if (!opt_initialize) { |
| 255 |
1/2✓ Branch 0 taken 10204 times.
✗ Branch 1 not taken.
|
10204 | log_pfs_release_services(reg_srv); |
| 256 | } | ||
| 257 |
1/2✓ Branch 0 taken 10504 times.
✗ Branch 1 not taken.
|
10504 | innobase::encryption::deinit_keyring_services(reg_srv); |
| 258 |
2/2✓ Branch 0 taken 10496 times.
✓ Branch 1 taken 8 times.
|
10504 | if (reg_srv != nullptr) { |
| 259 |
1/2✓ Branch 0 taken 10496 times.
✗ Branch 1 not taken.
|
10496 | mysql_plugin_registry_release(reg_srv); |
| 260 | } | ||
| 261 | 10504 | } | |
| 262 | |||
| 263 | } // namespace component_services | ||
| 264 | } // namespace innobase | ||
| 265 | |||
| 266 | /** Stop printing warnings, if the count exceeds this threshold. */ | ||
| 267 | static const size_t MOVED_FILES_PRINT_THRESHOLD = 32; | ||
| 268 | |||
| 269 | SERVICE_TYPE(registry) * reg_svc; | ||
| 270 | SERVICE_TYPE(system_variable_source) * sysvar_source_svc; | ||
| 271 | SERVICE_TYPE(clone_protocol) * clone_protocol_svc; | ||
| 272 | |||
| 273 | static const uint64_t KB = 1024; | ||
| 274 | static const uint64_t MB = KB * 1024; | ||
| 275 | static const uint64_t GB = MB * 1024; | ||
| 276 | |||
| 277 | /** fil_space_t::flags for hard-coded tablespaces */ | ||
| 278 | uint32_t predefined_flags; | ||
| 279 | |||
| 280 | /** to protect innobase_open_files */ | ||
| 281 | static mysql_mutex_t innobase_share_mutex; | ||
| 282 | |||
| 283 | /* mutex protecting the master_key_id change. */ | ||
| 284 | ib_mutex_t master_key_id_mutex; | ||
| 285 | |||
| 286 | /** to force correct commit order in binlog */ | ||
| 287 | static ulong commit_threads = 0; | ||
| 288 | static mysql_cond_t commit_cond; | ||
| 289 | static mysql_mutex_t commit_cond_m; | ||
| 290 | mysql_cond_t resume_encryption_cond; | ||
| 291 | mysql_mutex_t resume_encryption_cond_m; | ||
| 292 | bool innodb_inited = false; | ||
| 293 | |||
| 294 | 3939808180 | [[maybe_unused]] static inline bool EQ_CURRENT_THD(THD *thd) { | |
| 295 | 3939808180 | return thd == current_thd; | |
| 296 | } | ||
| 297 | |||
| 298 | static struct handlerton *innodb_hton_ptr; | ||
| 299 | |||
| 300 | static const long AUTOINC_OLD_STYLE_LOCKING = 0; | ||
| 301 | static const long AUTOINC_NEW_STYLE_LOCKING = 1; | ||
| 302 | static const long AUTOINC_NO_LOCKING = 2; | ||
| 303 | |||
| 304 | static long innobase_open_files; | ||
| 305 | static long innobase_autoinc_lock_mode; | ||
| 306 | static ulong innobase_commit_concurrency = 0; | ||
| 307 | |||
| 308 | /* Boolean @@innodb_buffer_pool_in_core_file. */ | ||
| 309 | bool srv_buffer_pool_in_core_file = true; | ||
| 310 | |||
| 311 | /** Percentage of the buffer pool to reserve for 'old' blocks. | ||
| 312 | Connected to buf_LRU_old_ratio. */ | ||
| 313 | static uint innobase_old_blocks_pct; | ||
| 314 | |||
| 315 | /* The default values for the following char* start-up parameters | ||
| 316 | are determined in innodb_init_params(). */ | ||
| 317 | |||
| 318 | static char *innobase_data_home_dir = nullptr; | ||
| 319 | static char *innobase_data_file_path = nullptr; | ||
| 320 | static char *innobase_temp_data_file_path = nullptr; | ||
| 321 | static char *innobase_enable_monitor_counter = nullptr; | ||
| 322 | static char *innobase_disable_monitor_counter = nullptr; | ||
| 323 | static char *innobase_reset_monitor_counter = nullptr; | ||
| 324 | static char *innobase_reset_all_monitor_counter = nullptr; | ||
| 325 | static char *innobase_doublewrite_dir = nullptr; | ||
| 326 | |||
| 327 | static ulong innodb_flush_method; | ||
| 328 | |||
| 329 | /* This variable can be set in the server configure file, specifying | ||
| 330 | stopword table to be used */ | ||
| 331 | static char *innobase_server_stopword_table = nullptr; | ||
| 332 | |||
| 333 | /* Below we have boolean-valued start-up parameters, and their default | ||
| 334 | values */ | ||
| 335 | |||
| 336 | static bool innobase_rollback_on_timeout = false; | ||
| 337 | static bool innobase_create_status_file = false; | ||
| 338 | bool innobase_stats_on_metadata = true; | ||
| 339 | static bool innodb_optimize_fulltext_only = false; | ||
| 340 | |||
| 341 | static char *innodb_version_str = (char *)INNODB_VERSION_STR; | ||
| 342 | |||
| 343 | static Innodb_data_lock_inspector innodb_data_lock_inspector; | ||
| 344 | |||
| 345 | static const uint MAX_ENCRYPTION_THREADS = 255; | ||
| 346 | extern uint srv_fil_crypt_rotate_key_age; | ||
| 347 | extern uint srv_n_fil_crypt_iops; | ||
| 348 | |||
| 349 | /** Path to the Percona-specific parallel doublewrite buffer (Deprecated) */ | ||
| 350 | static char *srv_parallel_doublewrite_path_deprecated = nullptr; | ||
| 351 | |||
| 352 | /** Enable or disable encryption of pages in parallel doublewrite buffer | ||
| 353 | file (Deprecated) */ | ||
| 354 | static bool srv_parallel_dblwr_encrypt_deprecated = false; | ||
| 355 | |||
| 356 | /** Note we cannot use rec_format_enum because we do not allow | ||
| 357 | COMPRESSED row format for innodb_default_row_format option. */ | ||
| 358 | enum default_row_format_enum { | ||
| 359 | DEFAULT_ROW_FORMAT_REDUNDANT = 0, | ||
| 360 | DEFAULT_ROW_FORMAT_COMPACT = 1, | ||
| 361 | DEFAULT_ROW_FORMAT_DYNAMIC = 2, | ||
| 362 | }; | ||
| 363 | |||
| 364 | #if defined(_WIN32) || defined(_WIN64) | ||
| 365 | #include <Windows.h> | ||
| 366 | static double get_mem_GlobalMemoryStatus() { | ||
| 367 | MEMORYSTATUSEX ms; | ||
| 368 | ms.dwLength = sizeof(ms); | ||
| 369 | GlobalMemoryStatusEx(&ms); | ||
| 370 | return (((double)ms.ullTotalPhys) / GB); | ||
| 371 | } | ||
| 372 | #undef get_sys_mem | ||
| 373 | #define get_sys_mem get_mem_GlobalMemoryStatus | ||
| 374 | #else | ||
| 375 | ✗ | static double get_mem_sysconf() { | |
| 376 | ✗ | return (((double)sysconf(_SC_PHYS_PAGES)) * | |
| 377 | ✗ | ((double)sysconf(_SC_PAGESIZE) / GB)); | |
| 378 | } | ||
| 379 | #undef get_sys_mem | ||
| 380 | #define get_sys_mem get_mem_sysconf | ||
| 381 | #endif /* defined(_WIN32) || defined(_WIN64) */ | ||
| 382 | |||
| 383 | /** Release all acquired services from mysql server. */ | ||
| 384 | 10504 | static void release_plugin_services() { | |
| 385 |
2/2✓ Branch 0 taken 87 times.
✓ Branch 1 taken 10417 times.
|
10504 | if (reg_svc == nullptr) { |
| 386 | 87 | return; | |
| 387 | } | ||
| 388 | |||
| 389 |
1/2✓ Branch 0 taken 10417 times.
✗ Branch 1 not taken.
|
10417 | if (sysvar_source_svc != nullptr) { |
| 390 | using sysvar_source_svc_t = SERVICE_TYPE_NO_CONST(system_variable_source); | ||
| 391 | 10417 | reg_svc->release(reinterpret_cast<my_h_service>( | |
| 392 | const_cast<sysvar_source_svc_t *>(sysvar_source_svc))); | ||
| 393 | 10417 | sysvar_source_svc = nullptr; | |
| 394 | } | ||
| 395 | |||
| 396 |
1/2✓ Branch 0 taken 10417 times.
✗ Branch 1 not taken.
|
10417 | if (clone_protocol_svc != nullptr) { |
| 397 | using clone_protocol_t = SERVICE_TYPE_NO_CONST(clone_protocol); | ||
| 398 | 10417 | reg_svc->release(reinterpret_cast<my_h_service>( | |
| 399 | const_cast<clone_protocol_t *>(clone_protocol_svc))); | ||
| 400 | 10417 | clone_protocol_svc = nullptr; | |
| 401 | } | ||
| 402 | |||
| 403 | /* Release registry service */ | ||
| 404 | 10417 | mysql_plugin_registry_release(reg_svc); | |
| 405 | 10417 | reg_svc = nullptr; | |
| 406 | } | ||
| 407 | |||
| 408 | /** Acquire required services from mysql server. */ | ||
| 409 | 12035 | static void acquire_plugin_services() { | |
| 410 | /* Acquire mysql_server's registry service */ | ||
| 411 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | reg_svc = mysql_plugin_registry_acquire(); |
| 412 | |||
| 413 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12035 times.
|
12035 | if (reg_svc == nullptr) { |
| 414 | ✗ | ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "plugin registry"); | |
| 415 | ✗ | return; | |
| 416 | } | ||
| 417 | |||
| 418 | my_h_service service; | ||
| 419 | |||
| 420 | /* Acquire system_variable_source service */ | ||
| 421 |
2/4✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12035 times.
|
12035 | if (reg_svc->acquire("system_variable_source", &service)) { |
| 422 | ✗ | ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "system_variable_source"); | |
| 423 | |||
| 424 | } else { | ||
| 425 | 12035 | sysvar_source_svc = | |
| 426 | reinterpret_cast<SERVICE_TYPE(system_variable_source) *>(service); | ||
| 427 | } | ||
| 428 | |||
| 429 | /* Acquire clone protocol service handle. */ | ||
| 430 |
2/4✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12035 times.
|
12035 | if (reg_svc->acquire("clone_protocol", &service)) { |
| 431 | ✗ | ib::warn(ER_IB_WRN_FAILED_TO_ACQUIRE_SERVICE, "clone_protocol"); | |
| 432 | |||
| 433 | } else { | ||
| 434 | 12035 | clone_protocol_svc = | |
| 435 | reinterpret_cast<SERVICE_TYPE(clone_protocol) *>(service); | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | /** Return the InnoDB ROW_FORMAT enum value | ||
| 440 | @param[in] row_format row_format from "innodb_default_row_format" | ||
| 441 | @return InnoDB ROW_FORMAT value from rec_format_t enum. */ | ||
| 442 | 428400 | static rec_format_t get_row_format(ulong row_format) { | |
| 443 |
3/4✓ Branch 0 taken 121 times.
✓ Branch 1 taken 227 times.
✓ Branch 2 taken 428052 times.
✗ Branch 3 not taken.
|
428400 | switch (row_format) { |
| 444 | 121 | case DEFAULT_ROW_FORMAT_REDUNDANT: | |
| 445 | 121 | return (REC_FORMAT_REDUNDANT); | |
| 446 | 227 | case DEFAULT_ROW_FORMAT_COMPACT: | |
| 447 | 227 | return (REC_FORMAT_COMPACT); | |
| 448 | 428052 | case DEFAULT_ROW_FORMAT_DYNAMIC: | |
| 449 | 428052 | return (REC_FORMAT_DYNAMIC); | |
| 450 | ✗ | default: | |
| 451 | ✗ | ut_d(ut_error); | |
| 452 | ut_o(return (REC_FORMAT_DYNAMIC)); | ||
| 453 | } | ||
| 454 | } | ||
| 455 | |||
| 456 | /** Note that a transaction has been deregistered. | ||
| 457 | @param[in] trx transaction */ | ||
| 458 | static void trx_deregister_from_2pc(trx_t *trx); | ||
| 459 | static ulong innodb_default_row_format = DEFAULT_ROW_FORMAT_DYNAMIC; | ||
| 460 | |||
| 461 | #ifdef UNIV_DEBUG | ||
| 462 | /** Values for --innodb-debug-compress names. */ | ||
| 463 | static const char *innodb_debug_compress_names[] = {"none", "zlib", "lz4", | ||
| 464 | "lz4hc", NullS}; | ||
| 465 | |||
| 466 | /** Enumeration of --innodb-debug-compress */ | ||
| 467 | static TYPELIB innodb_debug_compress_typelib = { | ||
| 468 | array_elements(innodb_debug_compress_names) - 1, | ||
| 469 | "innodb_debug_compress_typelib", innodb_debug_compress_names, nullptr}; | ||
| 470 | #endif /* UNIV_DEBUG */ | ||
| 471 | |||
| 472 | /** Possible values for system variable "innodb_stats_method". The values | ||
| 473 | are defined the same as its corresponding MyISAM system variable | ||
| 474 | "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */ | ||
| 475 | static const char *innodb_stats_method_names[] = { | ||
| 476 | "nulls_equal", "nulls_unequal", "nulls_ignored", NullS}; | ||
| 477 | |||
| 478 | /** Used to define an enumerate type of the system variable innodb_stats_method. | ||
| 479 | This is the same as "myisam_stats_method_typelib" */ | ||
| 480 | static TYPELIB innodb_stats_method_typelib = { | ||
| 481 | array_elements(innodb_stats_method_names) - 1, | ||
| 482 | "innodb_stats_method_typelib", innodb_stats_method_names, nullptr}; | ||
| 483 | |||
| 484 | #endif /* UNIV_HOTBACKUP */ | ||
| 485 | |||
| 486 | /** Possible values of the parameter innodb_checksum_algorithm */ | ||
| 487 | static const char *innodb_checksum_algorithm_names[] = { | ||
| 488 | "crc32", "strict_crc32", "innodb", "strict_innodb", | ||
| 489 | "none", "strict_none", NullS}; | ||
| 490 | |||
| 491 | /** Used to define an enumerate type of the system variable | ||
| 492 | innodb_checksum_algorithm. */ | ||
| 493 | static TYPELIB innodb_checksum_algorithm_typelib = { | ||
| 494 | array_elements(innodb_checksum_algorithm_names) - 1, | ||
| 495 | "innodb_checksum_algorithm_typelib", innodb_checksum_algorithm_names, | ||
| 496 | nullptr}; | ||
| 497 | |||
| 498 | #ifndef UNIV_HOTBACKUP | ||
| 499 | /** Names of allowed values of innodb_flush_method */ | ||
| 500 | static const char *innodb_flush_method_names[] = { | ||
| 501 | #ifndef _WIN32 /* See srv_unix_flush_t */ | ||
| 502 | "fsync", "O_DSYNC", "littlesync", "nosync", "O_DIRECT", "O_DIRECT_NO_FSYNC", | ||
| 503 | #else /* _WIN32; see srv_win_flush_t */ | ||
| 504 | "unbuffered", "normal", | ||
| 505 | #endif | ||
| 506 | NullS}; | ||
| 507 | |||
| 508 | /** Enumeration of innodb_flush_method */ | ||
| 509 | static TYPELIB innodb_flush_method_typelib = { | ||
| 510 | array_elements(innodb_flush_method_names) - 1, | ||
| 511 | "innodb_flush_method_typelib", innodb_flush_method_names, nullptr}; | ||
| 512 | |||
| 513 | /** Possible values for system variable "innodb_cleaner_lsn_age_factor". */ | ||
| 514 | static const char *innodb_cleaner_lsn_age_factor_names[] = { | ||
| 515 | "legacy", "high_checkpoint", NullS}; | ||
| 516 | |||
| 517 | /** Enumeration for innodb_cleaner_lsn_age_factor. */ | ||
| 518 | static TYPELIB innodb_cleaner_lsn_age_factor_typelib = { | ||
| 519 | array_elements(innodb_cleaner_lsn_age_factor_names) - 1, | ||
| 520 | "innodb_cleaner_lsn_age_factor_typelib", | ||
| 521 | innodb_cleaner_lsn_age_factor_names, nullptr}; | ||
| 522 | |||
| 523 | /** Possible values for system variable "innodb_empty_free_list_algorithm". */ | ||
| 524 | static const char *innodb_empty_free_list_algorithm_names[] = { | ||
| 525 | "legacy", "backoff", NullS}; | ||
| 526 | |||
| 527 | /** Enumeration for innodb_empty_free_list_algorithm. */ | ||
| 528 | static TYPELIB innodb_empty_free_list_algorithm_typelib = { | ||
| 529 | array_elements(innodb_empty_free_list_algorithm_names) - 1, | ||
| 530 | "innodb_empty_free_list_algorithm_typelib", | ||
| 531 | innodb_empty_free_list_algorithm_names, nullptr}; | ||
| 532 | |||
| 533 | /** Possible values for system variable "innodb_default_row_format". */ | ||
| 534 | static const char *innodb_default_row_format_names[] = {"redundant", "compact", | ||
| 535 | "dynamic", NullS}; | ||
| 536 | |||
| 537 | /** Used to define an enumerate type of the system variable | ||
| 538 | innodb_default_row_format. */ | ||
| 539 | static TYPELIB innodb_default_row_format_typelib = { | ||
| 540 | array_elements(innodb_default_row_format_names) - 1, | ||
| 541 | "innodb_default_row_format_typelib", innodb_default_row_format_names, | ||
| 542 | nullptr}; | ||
| 543 | |||
| 544 | /** Possible values for system variable "innodb_doublewrite". | ||
| 545 | @note: If you change order or add new values, please update dblwr::mode_t. */ | ||
| 546 | static const char *innodb_doublewrite_names[] = { | ||
| 547 | "OFF", "ON", "DETECT_ONLY", "DETECT_AND_RECOVER", "FALSE", "TRUE", NullS}; | ||
| 548 | |||
| 549 | /** Used to define an enumerate type of the system variable | ||
| 550 | innodb_default_row_format. */ | ||
| 551 | static TYPELIB innodb_doublewrite_typelib = { | ||
| 552 | array_elements(innodb_doublewrite_names) - 1, "innodb_doublewrite_typelib", | ||
| 553 | innodb_doublewrite_names, nullptr}; | ||
| 554 | |||
| 555 | #else /* !UNIV_HOTBACKUP */ | ||
| 556 | |||
| 557 | /** Returns the name of the checksum algorithm corresponding to the | ||
| 558 | algorithm id given by "algo_enum" parameter. | ||
| 559 | @param[in] algo_enum algorithm enumerator | ||
| 560 | @return C-string algorithm name */ | ||
| 561 | const char *meb_get_checksum_algorithm_name( | ||
| 562 | srv_checksum_algorithm_t algo_enum) { | ||
| 563 | return (get_type(&innodb_checksum_algorithm_typelib, algo_enum)); | ||
| 564 | } | ||
| 565 | |||
| 566 | /** Retrieves the enum corresponding to the checksum algorithm | ||
| 567 | name specified by algo_name. If the call succeeds, returns | ||
| 568 | true and checksum algorithm enum is returned in algo_enum. | ||
| 569 | @param[in] algo_name algorithm name | ||
| 570 | @param[out] algo_enum algorithm enumerator | ||
| 571 | @retval true if successful | ||
| 572 | @retval false if algorithn name not found */ | ||
| 573 | bool meb_get_checksum_algorithm_enum(const char *algo_name, | ||
| 574 | srv_checksum_algorithm_t &algo_enum) { | ||
| 575 | int type = | ||
| 576 | find_type(algo_name, &innodb_checksum_algorithm_typelib, FIND_TYPE_BASIC); | ||
| 577 | if (type <= 0) { | ||
| 578 | /** Invalid algorithm name */ | ||
| 579 | return false; | ||
| 580 | } else { | ||
| 581 | algo_enum = srv_checksum_algorithm_t(type - 1); | ||
| 582 | } | ||
| 583 | |||
| 584 | return true; | ||
| 585 | } | ||
| 586 | #endif /* !UNIV_HOTBACKUP */ | ||
| 587 | |||
| 588 | static const char *sys_tablespace_encrypt_names[] = { | ||
| 589 | "OFF", "ON", "RE_ENCRYPTING_TO_KEYRING", NullS}; | ||
| 590 | static TYPELIB sys_tablespace_encrypt_typelib = { | ||
| 591 | array_elements(sys_tablespace_encrypt_names) - 1, | ||
| 592 | "sys_tablespace_encrypt_typelib", sys_tablespace_encrypt_names, nullptr}; | ||
| 593 | |||
| 594 | #ifndef UNIV_HOTBACKUP | ||
| 595 | /* The following counter is used to convey information to InnoDB | ||
| 596 | about server activity: in case of normal DML ops it is not | ||
| 597 | sensible to call srv_active_wake_master_thread after each | ||
| 598 | operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */ | ||
| 599 | |||
| 600 | constexpr uint32_t INNOBASE_WAKE_INTERVAL = 32; | ||
| 601 | static ulong innobase_active_counter = 0; | ||
| 602 | |||
| 603 | static hash_table_t *innobase_open_tables; | ||
| 604 | |||
| 605 | /** Array of data files of the system tablespace */ | ||
| 606 | static std::vector<Plugin_tablespace::Plugin_tablespace_file *, | ||
| 607 | ut::allocator<Plugin_tablespace::Plugin_tablespace_file *>> | ||
| 608 | innobase_sys_files; | ||
| 609 | |||
| 610 | /** Allowed values of innodb_change_buffering */ | ||
| 611 | static const char *innodb_change_buffering_names[] = { | ||
| 612 | "none", /* IBUF_USE_NONE */ | ||
| 613 | "inserts", /* IBUF_USE_INSERT */ | ||
| 614 | "deletes", /* IBUF_USE_DELETE_MARK */ | ||
| 615 | "changes", /* IBUF_USE_INSERT_DELETE_MARK */ | ||
| 616 | "purges", /* IBUF_USE_DELETE */ | ||
| 617 | "all", /* IBUF_USE_ALL */ | ||
| 618 | NullS}; | ||
| 619 | |||
| 620 | /** Enumeration of innodb_change_buffering */ | ||
| 621 | static TYPELIB innodb_change_buffering_typelib = { | ||
| 622 | array_elements(innodb_change_buffering_names) - 1, | ||
| 623 | "innodb_change_buffering_typelib", innodb_change_buffering_names, nullptr}; | ||
| 624 | |||
| 625 | /** Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 626 | of m_prebuilt->fts_doc_id | ||
| 627 | @param[in,out] fts_hdl FTS handler | ||
| 628 | @return the relevance ranking value */ | ||
| 629 | static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl); | ||
| 630 | /** Free the memory for the FTS handler | ||
| 631 | @param[in,out] fts_hdl FTS handler */ | ||
| 632 | static void innobase_fts_close_ranking(FT_INFO *fts_hdl); | ||
| 633 | |||
| 634 | /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 635 | of m_prebuilt->fts_doc_id | ||
| 636 | @param[in,out] fts_hdl FTS handler | ||
| 637 | @return the relevance ranking value */ | ||
| 638 | static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint); | ||
| 639 | |||
| 640 | /* Call back function array defined by MySQL and used to | ||
| 641 | retrieve FTS results. */ | ||
| 642 | const struct _ft_vft ft_vft_result = {nullptr, innobase_fts_find_ranking, | ||
| 643 | innobase_fts_close_ranking, | ||
| 644 | innobase_fts_retrieve_ranking, nullptr}; | ||
| 645 | |||
| 646 | /** @return version of the extended FTS API */ | ||
| 647 | ✗ | static uint innobase_fts_get_version() { | |
| 648 | /* Currently this doesn't make much sense as returning | ||
| 649 | HA_CAN_FULLTEXT_EXT automatically mean this version is supported. | ||
| 650 | This supposed to ease future extensions. */ | ||
| 651 | ✗ | return (2); | |
| 652 | } | ||
| 653 | |||
| 654 | /** @return Which part of the extended FTS API is supported */ | ||
| 655 | 169 | static ulonglong innobase_fts_flags() { | |
| 656 | 169 | return (FTS_ORDERED_RESULT | FTS_DOCID_IN_RESULT); | |
| 657 | } | ||
| 658 | |||
| 659 | /** Find and Retrieve the FTS doc_id for the current result row | ||
| 660 | @param[in,out] fts_hdl FTS handler | ||
| 661 | @return the document ID */ | ||
| 662 | static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl); | ||
| 663 | |||
| 664 | /** Find and retrieve the size of the current result | ||
| 665 | @param[in,out] fts_hdl FTS handler | ||
| 666 | @return number of matching rows */ | ||
| 667 | 152 | static ulonglong innobase_fts_count_matches( | |
| 668 | FT_INFO_EXT *fts_hdl) /*!< in: FTS handler */ | ||
| 669 | { | ||
| 670 | 152 | NEW_FT_INFO *handle = reinterpret_cast<NEW_FT_INFO *>(fts_hdl); | |
| 671 | |||
| 672 |
2/2✓ Branch 0 taken 137 times.
✓ Branch 1 taken 15 times.
|
152 | if (handle->ft_result->rankings_by_id != nullptr) { |
| 673 | 137 | return (rbt_size(handle->ft_result->rankings_by_id)); | |
| 674 | } else { | ||
| 675 | 15 | return (0); | |
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | const struct _ft_vft_ext ft_vft_ext_result = { | ||
| 680 | innobase_fts_get_version, innobase_fts_flags, innobase_fts_retrieve_docid, | ||
| 681 | innobase_fts_count_matches}; | ||
| 682 | |||
| 683 | #ifdef HAVE_PSI_INTERFACE | ||
| 684 | #define PSI_KEY(n, flag, volatility, doc) \ | ||
| 685 | { &(n##_key.m_value), #n, flag, volatility, doc } | ||
| 686 | #define PSI_MEMORY_KEY(n, flag, volatility, doc) \ | ||
| 687 | { &(n##_key), #n, flag, volatility, doc } | ||
| 688 | #define PSI_MUTEX_KEY(n, flag, volatility, doc) \ | ||
| 689 | { &(n##_key.m_value), #n, flag, volatility, doc } | ||
| 690 | /* All RWLOCK used in Innodb are SX-locks */ | ||
| 691 | #define PSI_RWLOCK_KEY(n, volatility, doc) \ | ||
| 692 | { &n##_key.m_value, #n, PSI_FLAG_RWLOCK_SX, volatility, doc } | ||
| 693 | #define PSI_THREAD_KEY(n, osn, flag, volatility, doc) \ | ||
| 694 | { &(n##_key.m_value), #n, osn, flag, volatility, doc } | ||
| 695 | |||
| 696 | /* Keys to register pthread mutexes/cond in the current file with | ||
| 697 | performance schema */ | ||
| 698 | static mysql_pfs_key_t innobase_share_mutex_key; | ||
| 699 | static mysql_pfs_key_t commit_cond_mutex_key; | ||
| 700 | static mysql_pfs_key_t commit_cond_key; | ||
| 701 | mysql_pfs_key_t resume_encryption_cond_mutex_key; | ||
| 702 | mysql_pfs_key_t resume_encryption_cond_key; | ||
| 703 | |||
| 704 | static PSI_mutex_info all_pthread_mutexes[] = { | ||
| 705 | PSI_MUTEX_KEY(commit_cond_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 706 | PSI_MUTEX_KEY(innobase_share_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 707 | PSI_MUTEX_KEY(resume_encryption_cond_mutex, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 708 | |||
| 709 | static PSI_cond_info all_innodb_conds[] = { | ||
| 710 | PSI_KEY(commit_cond, 0, 0, PSI_DOCUMENT_ME), | ||
| 711 | PSI_KEY(resume_encryption_cond, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 712 | |||
| 713 | #ifdef UNIV_PFS_MEMORY | ||
| 714 | /* pfs keys related to memory that is performance schema instrumented | ||
| 715 | when "UNIV_PFS_MEMORY" is defined */ | ||
| 716 | static PSI_memory_info pfs_instrumented_innodb_memory[] = { | ||
| 717 | PSI_MEMORY_KEY(log_buffer_memory, 0, 0, "Redo log buffer")}; | ||
| 718 | #endif /* UNIV_PFS_MEMORY */ | ||
| 719 | |||
| 720 | #ifdef UNIV_PFS_MUTEX | ||
| 721 | /* all_innodb_mutexes array contains mutexes that are | ||
| 722 | performance schema instrumented if "UNIV_PFS_MUTEX" | ||
| 723 | is defined */ | ||
| 724 | static PSI_mutex_info all_innodb_mutexes[] = { | ||
| 725 | PSI_MUTEX_KEY(autoinc_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 726 | PSI_MUTEX_KEY(autoinc_persisted_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 727 | #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK | ||
| 728 | PSI_MUTEX_KEY(buffer_block_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 729 | #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */ | ||
| 730 | PSI_MUTEX_KEY(buf_pool_chunks_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 731 | PSI_MUTEX_KEY(buf_pool_flush_state_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 732 | PSI_MUTEX_KEY(buf_pool_LRU_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 733 | PSI_MUTEX_KEY(buf_pool_free_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 734 | PSI_MUTEX_KEY(buf_pool_zip_free_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 735 | PSI_MUTEX_KEY(buf_pool_zip_hash_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 736 | PSI_MUTEX_KEY(buf_pool_zip_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 737 | PSI_MUTEX_KEY(clone_snapshot_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 738 | PSI_MUTEX_KEY(clone_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 739 | PSI_MUTEX_KEY(clone_task_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 740 | PSI_MUTEX_KEY(ddl_autoinc_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 741 | PSI_MUTEX_KEY(dict_foreign_err_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 742 | PSI_MUTEX_KEY(dict_persist_dirty_tables_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 743 | PSI_MUTEX_KEY(dict_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 744 | PSI_MUTEX_KEY(dict_table_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 745 | PSI_MUTEX_KEY(parser_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 746 | PSI_MUTEX_KEY(recalc_pool_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 747 | PSI_MUTEX_KEY(fil_system_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 748 | PSI_MUTEX_KEY(file_open_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 749 | PSI_MUTEX_KEY(flush_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 750 | PSI_MUTEX_KEY(fts_bg_threads_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 751 | PSI_MUTEX_KEY(fts_delete_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 752 | PSI_MUTEX_KEY(fts_optimize_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 753 | PSI_MUTEX_KEY(fts_doc_id_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 754 | PSI_MUTEX_KEY(fts_pll_tokenize_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 755 | PSI_MUTEX_KEY(hash_table_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 756 | PSI_MUTEX_KEY(ibuf_bitmap_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 757 | PSI_MUTEX_KEY(ibuf_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 758 | PSI_MUTEX_KEY(ibuf_pessimistic_insert_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 759 | PSI_MUTEX_KEY(lock_free_hash_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 760 | PSI_MUTEX_KEY(log_limits_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 761 | PSI_MUTEX_KEY(log_files_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 762 | PSI_MUTEX_KEY(log_checkpointer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 763 | PSI_MUTEX_KEY(log_closer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 764 | PSI_MUTEX_KEY(log_writer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 765 | PSI_MUTEX_KEY(log_flusher_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 766 | PSI_MUTEX_KEY(log_write_notifier_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 767 | PSI_MUTEX_KEY(log_flush_notifier_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 768 | PSI_MUTEX_KEY(log_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 769 | PSI_MUTEX_KEY(log_cmdq_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 770 | PSI_MUTEX_KEY(log_sn_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 771 | PSI_MUTEX_KEY(mutex_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 772 | PSI_MUTEX_KEY(page_sys_arch_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 773 | PSI_MUTEX_KEY(page_sys_arch_oper_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 774 | PSI_MUTEX_KEY(page_sys_arch_client_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 775 | PSI_MUTEX_KEY(page_zip_stat_per_index_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 776 | PSI_MUTEX_KEY(page_cleaner_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 777 | PSI_MUTEX_KEY(parallel_read_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 778 | PSI_MUTEX_KEY(dblwr_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 779 | PSI_MUTEX_KEY(purge_sys_pq_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 780 | PSI_MUTEX_KEY(recv_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 781 | PSI_MUTEX_KEY(recv_writer_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 782 | PSI_MUTEX_KEY(temp_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 783 | PSI_MUTEX_KEY(undo_space_rseg_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 784 | PSI_MUTEX_KEY(trx_sys_rseg_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 785 | #ifdef UNIV_DEBUG | ||
| 786 | PSI_MUTEX_KEY(rw_lock_debug_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 787 | #endif /* UNIV_DEBUG */ | ||
| 788 | PSI_MUTEX_KEY(rw_lock_list_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 789 | PSI_MUTEX_KEY(rw_lock_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 790 | PSI_MUTEX_KEY(srv_innodb_monitor_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 791 | PSI_MUTEX_KEY(srv_misc_tmpfile_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 792 | PSI_MUTEX_KEY(srv_monitor_file_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 793 | #ifdef UNIV_DEBUG | ||
| 794 | PSI_MUTEX_KEY(sync_thread_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 795 | #endif /* UNIV_DEBUG */ | ||
| 796 | PSI_MUTEX_KEY(trx_undo_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 797 | PSI_MUTEX_KEY(trx_pool_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 798 | PSI_MUTEX_KEY(trx_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 799 | PSI_MUTEX_KEY(temp_pool_manager_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 800 | PSI_MUTEX_KEY(srv_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 801 | PSI_MUTEX_KEY(lock_sys_page_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 802 | PSI_MUTEX_KEY(lock_sys_table_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 803 | PSI_MUTEX_KEY(lock_wait_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 804 | PSI_MUTEX_KEY(trx_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 805 | PSI_MUTEX_KEY(srv_threads_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 806 | #ifndef PFS_SKIP_EVENT_MUTEX | ||
| 807 | PSI_MUTEX_KEY(event_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 808 | PSI_MUTEX_KEY(event_manager_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 809 | #endif /* PFS_SKIP_EVENT_MUTEX */ | ||
| 810 | PSI_MUTEX_KEY(rtr_active_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 811 | PSI_MUTEX_KEY(rtr_match_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 812 | PSI_MUTEX_KEY(rtr_path_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 813 | PSI_MUTEX_KEY(rtr_ssn_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 814 | PSI_MUTEX_KEY(trx_sys_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 815 | PSI_MUTEX_KEY(trx_sys_shard_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 816 | PSI_MUTEX_KEY(trx_sys_serialisation_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 817 | PSI_MUTEX_KEY(zip_pad_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 818 | PSI_MUTEX_KEY(master_key_id_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 819 | PSI_MUTEX_KEY(sync_array_mutex, 0, 0, PSI_DOCUMENT_ME), | ||
| 820 | PSI_MUTEX_KEY(row_drop_list_mutex, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 821 | #endif /* UNIV_PFS_MUTEX */ | ||
| 822 | |||
| 823 | #ifdef UNIV_PFS_RWLOCK | ||
| 824 | /* all_innodb_rwlocks array contains rwlocks that are | ||
| 825 | performance schema instrumented if "UNIV_PFS_RWLOCK" | ||
| 826 | is defined */ | ||
| 827 | static PSI_rwlock_info all_innodb_rwlocks[] = { | ||
| 828 | PSI_RWLOCK_KEY(btr_search_latch, 0, PSI_DOCUMENT_ME), | ||
| 829 | #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK | ||
| 830 | PSI_RWLOCK_KEY(buf_block_lock, 0, PSI_DOCUMENT_ME), | ||
| 831 | #endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */ | ||
| 832 | #ifdef UNIV_DEBUG | ||
| 833 | PSI_RWLOCK_KEY(buf_block_debug_latch, 0, PSI_DOCUMENT_ME), | ||
| 834 | #endif /* UNIV_DEBUG */ | ||
| 835 | PSI_RWLOCK_KEY(dict_operation_lock, 0, PSI_DOCUMENT_ME), | ||
| 836 | PSI_RWLOCK_KEY(fil_space_latch, 0, PSI_DOCUMENT_ME), | ||
| 837 | PSI_RWLOCK_KEY(log_sn_lock, 0, PSI_DOCUMENT_ME), | ||
| 838 | PSI_RWLOCK_KEY(undo_spaces_lock, 0, PSI_DOCUMENT_ME), | ||
| 839 | PSI_RWLOCK_KEY(rsegs_lock, 0, PSI_DOCUMENT_ME), | ||
| 840 | PSI_RWLOCK_KEY(lock_sys_global_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 841 | PSI_RWLOCK_KEY(fts_cache_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 842 | PSI_RWLOCK_KEY(fts_cache_init_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 843 | PSI_RWLOCK_KEY(trx_i_s_cache_lock, 0, PSI_DOCUMENT_ME), | ||
| 844 | PSI_RWLOCK_KEY(trx_purge_latch, 0, PSI_DOCUMENT_ME), | ||
| 845 | PSI_RWLOCK_KEY(index_tree_rw_lock, 0, PSI_DOCUMENT_ME), | ||
| 846 | PSI_RWLOCK_KEY(index_online_log, 0, PSI_DOCUMENT_ME), | ||
| 847 | PSI_RWLOCK_KEY(dict_table_stats, 0, PSI_DOCUMENT_ME), | ||
| 848 | PSI_RWLOCK_KEY(hash_table_locks, 0, PSI_DOCUMENT_ME), | ||
| 849 | }; | ||
| 850 | #endif /* UNIV_PFS_RWLOCK */ | ||
| 851 | |||
| 852 | #ifdef UNIV_PFS_THREAD | ||
| 853 | /* all_innodb_threads array contains threads that are | ||
| 854 | performance schema instrumented if "UNIV_PFS_THREAD" | ||
| 855 | is defined */ | ||
| 856 | static PSI_thread_info all_innodb_threads[] = { | ||
| 857 | PSI_THREAD_KEY(log_archiver_thread, "ib_log_arch", PSI_FLAG_SINGLETON, 0, | ||
| 858 | PSI_DOCUMENT_ME), | ||
| 859 | PSI_THREAD_KEY(page_archiver_thread, "ib_page_arch", PSI_FLAG_SINGLETON, 0, | ||
| 860 | PSI_DOCUMENT_ME), | ||
| 861 | PSI_THREAD_KEY(buf_dump_thread, "ib_buf_dump", PSI_FLAG_SINGLETON, 0, | ||
| 862 | PSI_DOCUMENT_ME), | ||
| 863 | PSI_THREAD_KEY(clone_ddl_thread, "ib_clone_ddl", PSI_FLAG_SINGLETON, 0, | ||
| 864 | PSI_DOCUMENT_ME), | ||
| 865 | PSI_THREAD_KEY(clone_gtid_thread, "ib_clone_gtid", PSI_FLAG_SINGLETON, 0, | ||
| 866 | PSI_DOCUMENT_ME), | ||
| 867 | PSI_THREAD_KEY(ddl_thread, "ib_ddl", 0, 0, PSI_DOCUMENT_ME), | ||
| 868 | PSI_THREAD_KEY(dict_stats_thread, "ib_dict_stats", PSI_FLAG_SINGLETON, 0, | ||
| 869 | PSI_DOCUMENT_ME), | ||
| 870 | PSI_THREAD_KEY(io_handler_thread, "ib_io_handler", PSI_FLAG_SINGLETON, 0, | ||
| 871 | PSI_DOCUMENT_ME), | ||
| 872 | PSI_THREAD_KEY(io_ibuf_thread, "ib_io_ibuf", PSI_FLAG_SINGLETON, 0, | ||
| 873 | PSI_DOCUMENT_ME), | ||
| 874 | PSI_THREAD_KEY(io_log_thread, "ib_io_log", PSI_FLAG_SINGLETON, 0, | ||
| 875 | PSI_DOCUMENT_ME), | ||
| 876 | PSI_THREAD_KEY(io_read_thread, "ib_io_rd", 0, 0, PSI_DOCUMENT_ME), | ||
| 877 | PSI_THREAD_KEY(io_write_thread, "ib_io_wr", 0, 0, PSI_DOCUMENT_ME), | ||
| 878 | PSI_THREAD_KEY(buf_resize_thread, "ib_buf_resize", PSI_FLAG_SINGLETON, 0, | ||
| 879 | PSI_DOCUMENT_ME), | ||
| 880 | PSI_THREAD_KEY(log_files_governor_thread, "ib_log_files_g", | ||
| 881 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 882 | PSI_THREAD_KEY(log_writer_thread, "ib_log_writer", PSI_FLAG_SINGLETON, 0, | ||
| 883 | PSI_DOCUMENT_ME), | ||
| 884 | PSI_THREAD_KEY(log_checkpointer_thread, "ib_log_checkpt", | ||
| 885 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 886 | PSI_THREAD_KEY(log_flusher_thread, "ib_log_flush", PSI_FLAG_SINGLETON, 0, | ||
| 887 | PSI_DOCUMENT_ME), | ||
| 888 | PSI_THREAD_KEY(log_write_notifier_thread, "ib_log_wr_notif", | ||
| 889 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 890 | PSI_THREAD_KEY(log_flush_notifier_thread, "ib_log_fl_notif", | ||
| 891 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 892 | PSI_THREAD_KEY(buf_lru_manager_thread, "ib_buf_lru", 0, 0, | ||
| 893 | PSI_DOCUMENT_ME), | ||
| 894 | PSI_THREAD_KEY(recv_writer_thread, "ib_recv_write", PSI_FLAG_SINGLETON, 0, | ||
| 895 | PSI_DOCUMENT_ME), | ||
| 896 | PSI_THREAD_KEY(srv_error_monitor_thread, "ib_srv_err", | ||
| 897 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 898 | PSI_THREAD_KEY(srv_lock_timeout_thread, "ib_srv_lock_to", | ||
| 899 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 900 | PSI_THREAD_KEY(srv_master_thread, "ib_src_main", PSI_FLAG_SINGLETON, 0, | ||
| 901 | PSI_DOCUMENT_ME), | ||
| 902 | PSI_THREAD_KEY(srv_monitor_thread, "ib_srv_mon", PSI_FLAG_SINGLETON, 0, | ||
| 903 | PSI_DOCUMENT_ME), | ||
| 904 | PSI_THREAD_KEY(srv_purge_thread, "ib_srv_purge", PSI_FLAG_SINGLETON, 0, | ||
| 905 | PSI_DOCUMENT_ME), | ||
| 906 | PSI_THREAD_KEY(srv_worker_thread, "ib_srv_wkr", 0, 0, PSI_DOCUMENT_ME), | ||
| 907 | PSI_THREAD_KEY(trx_recovery_rollback_thread, "ib_tx_recov", 0, 0, | ||
| 908 | PSI_DOCUMENT_ME), | ||
| 909 | PSI_THREAD_KEY(page_flush_thread, "ib_pg_flush", 0, 0, PSI_DOCUMENT_ME), | ||
| 910 | PSI_THREAD_KEY(page_flush_coordinator_thread, "ib_pg_flush_co", | ||
| 911 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 912 | PSI_THREAD_KEY(fts_optimize_thread, "ib_fts_opt", PSI_FLAG_SINGLETON, 0, | ||
| 913 | PSI_DOCUMENT_ME), | ||
| 914 | PSI_THREAD_KEY(fts_parallel_merge_thread, "ib_fts_merge", 0, 0, | ||
| 915 | PSI_DOCUMENT_ME), | ||
| 916 | PSI_THREAD_KEY(fts_parallel_tokenization_thread, "ib_fts_token", 0, 0, | ||
| 917 | PSI_DOCUMENT_ME), | ||
| 918 | PSI_THREAD_KEY(srv_ts_alter_encrypt_thread, "ib_ts_encrypt", | ||
| 919 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME), | ||
| 920 | PSI_THREAD_KEY(parallel_read_thread, "ib_par_rd", 0, 0, PSI_DOCUMENT_ME), | ||
| 921 | PSI_THREAD_KEY(parallel_rseg_init_thread, "ib_par_rseg", 0, 0, | ||
| 922 | PSI_DOCUMENT_ME), | ||
| 923 | PSI_THREAD_KEY(meb::redo_log_archive_consumer_thread, "ib_meb_rl", | ||
| 924 | PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME)}; | ||
| 925 | #endif /* UNIV_PFS_THREAD */ | ||
| 926 | |||
| 927 | #ifdef UNIV_PFS_IO | ||
| 928 | /* all_innodb_files array contains the type of files that are | ||
| 929 | performance schema instrumented if "UNIV_PFS_IO" is defined */ | ||
| 930 | static PSI_file_info all_innodb_files[] = { | ||
| 931 | PSI_KEY(innodb_dblwr_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 932 | PSI_KEY(innodb_tablespace_open_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 933 | PSI_KEY(innodb_data_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 934 | PSI_KEY(innodb_log_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 935 | PSI_KEY(innodb_bmp_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 936 | PSI_KEY(innodb_temp_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 937 | PSI_KEY(innodb_arch_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 938 | PSI_KEY(innodb_clone_file, 0, 0, PSI_DOCUMENT_ME), | ||
| 939 | PSI_KEY(meb::redo_log_archive_file, 0, 0, PSI_DOCUMENT_ME)}; | ||
| 940 | #endif /* UNIV_PFS_IO */ | ||
| 941 | #endif /* HAVE_PSI_INTERFACE */ | ||
| 942 | |||
| 943 | 13 | static int default_encryption_key_id_validate( | |
| 944 | /*=================================*/ | ||
| 945 | THD *thd, /*!< in: thread handle */ | ||
| 946 | SYS_VAR *var, /*!< in: pointer to system | ||
| 947 | variable */ | ||
| 948 | void *save, /*!< out: immediate result | ||
| 949 | for update function */ | ||
| 950 | st_mysql_value *value) /*!< in: incoming string */ { | ||
| 951 | long long intbuf; | ||
| 952 | |||
| 953 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | DBUG_ENTER("default_encryption_key_id_validate"); |
| 954 | |||
| 955 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | if (value->val_int(value, &intbuf)) { |
| 956 | /* The value is NULL. That is invalid. */ | ||
| 957 | ✗ | DBUG_RETURN(1); | |
| 958 | } | ||
| 959 | |||
| 960 | 13 | bool is_val_fixed = false; | |
| 961 | 13 | auto key_id = intbuf; | |
| 962 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
|
13 | if (intbuf < 0) { |
| 963 | 3 | key_id = 0; | |
| 964 | 3 | is_val_fixed = true; | |
| 965 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
|
10 | } else if (intbuf >= UINT_MAX32) { |
| 966 | 3 | key_id = UINT_MAX32 - 1; | |
| 967 | 3 | is_val_fixed = true; | |
| 968 | } | ||
| 969 | |||
| 970 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | if (throw_bounds_warning(thd, "innodb_encryption_key_id", is_val_fixed, |
| 971 | intbuf)) { | ||
| 972 | ✗ | DBUG_RETURN(1); | |
| 973 | } | ||
| 974 | |||
| 975 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist( |
| 976 | static_cast<uint>(key_id), server_uuid)) { | ||
| 977 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, | |
| 978 | "InnoDB: cannot enable encryption, " | ||
| 979 | "keyring plugin is not available"); | ||
| 980 | ✗ | DBUG_RETURN(1); | |
| 981 | } | ||
| 982 | |||
| 983 | 13 | *reinterpret_cast<ulong *>(save) = static_cast<ulong>(key_id); | |
| 984 | |||
| 985 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | DBUG_RETURN(0); |
| 986 | } | ||
| 987 | |||
| 988 | 13 | static void default_encryption_key_id_update( | |
| 989 | THD *thd, // in: thread handle <] | ||
| 990 | SYS_VAR *var, // in: pointer to | ||
| 991 | // system variable */ | ||
| 992 | void *var_ptr, // where the | ||
| 993 | // formal string goes */ | ||
| 994 | const void *save) { // in: immediate result | ||
| 995 | // from check function | ||
| 996 | 13 | *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save); | |
| 997 | 13 | } | |
| 998 | |||
| 999 | static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG, | ||
| 1000 | "Default encryption key id used for table encryption.", | ||
| 1001 | default_encryption_key_id_validate, | ||
| 1002 | default_encryption_key_id_update, | ||
| 1003 | FIL_DEFAULT_ENCRYPTION_KEY, 0, UINT_MAX32 - 1, 0); | ||
| 1004 | |||
| 1005 | 244 | uint get_global_default_encryption_key_id_value() { | |
| 1006 | 244 | return THDVAR(NULL, default_encryption_key_id); | |
| 1007 | } | ||
| 1008 | |||
| 1009 | static MYSQL_THDVAR_UINT(records_in_range, PLUGIN_VAR_RQCMDARG, | ||
| 1010 | "Used to override the result of records_in_range(). " | ||
| 1011 | "Set to a positive number to override", | ||
| 1012 | NULL, NULL, 0, | ||
| 1013 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1014 | |||
| 1015 | static MYSQL_THDVAR_UINT(force_index_records_in_range, PLUGIN_VAR_RQCMDARG, | ||
| 1016 | "Used to override the result of records_in_range() " | ||
| 1017 | "when FORCE INDEX is used.", | ||
| 1018 | NULL, NULL, 0, | ||
| 1019 | /* min */ 0, /* max */ INT_MAX, 0); | ||
| 1020 | |||
| 1021 | 39 | uint innodb_force_index_records_in_range(THD *thd) { | |
| 1022 | 39 | return THDVAR(thd, force_index_records_in_range); | |
| 1023 | } | ||
| 1024 | |||
| 1025 | 7917 | uint innodb_records_in_range(THD *thd) { return THDVAR(thd, records_in_range); } | |
| 1026 | |||
| 1027 | /** Plugin update function to handle validation and then switch the | ||
| 1028 | innodb_doublewrite mode | ||
| 1029 | @param[in] thd thread handle | ||
| 1030 | @param[in] var pointer to system variable | ||
| 1031 | @param[in] var_ptr where the formal string goes | ||
| 1032 | @param[in] save immediate result from check function */ | ||
| 1033 | 92 | static void doublewrite_update(THD *thd [[maybe_unused]], | |
| 1034 | SYS_VAR *var [[maybe_unused]], void *var_ptr, | ||
| 1035 | const void *save) { | ||
| 1036 | 92 | ulong new_value = *static_cast<const ulong *>(save); | |
| 1037 | |||
| 1038 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 75 times.
|
92 | if (dblwr::Mode::is_enabled_to_disabled(new_value)) { |
| 1039 | char msg[FN_REFLEN]; | ||
| 1040 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | snprintf(msg, sizeof(msg), |
| 1041 | "InnoDB: cannot change doublewrite mode to %s if" | ||
| 1042 | " doublewrite is enabled. Please shutdown and" | ||
| 1043 | " change value to %s", | ||
| 1044 | dblwr::Mode::to_string(new_value), | ||
| 1045 | dblwr::Mode::to_string(new_value)); | ||
| 1046 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | my_error(ER_WRONG_ARGUMENTS, MYF(0), msg); |
| 1047 | 17 | return; | |
| 1048 | } | ||
| 1049 | |||
| 1050 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 59 times.
|
75 | if (dblwr::Mode::is_disabled_to_enabled(new_value)) { |
| 1051 | char msg[FN_REFLEN]; | ||
| 1052 |
2/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | snprintf(msg, sizeof(msg), |
| 1053 | "InnoDB: cannot change doublewrite mode to %s if" | ||
| 1054 | " doublewrite is disabled. Please shutdown and" | ||
| 1055 | " change value to %s", | ||
| 1056 | dblwr::Mode::to_string(new_value), | ||
| 1057 | dblwr::Mode::to_string(new_value)); | ||
| 1058 | |||
| 1059 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | my_error(ER_WRONG_ARGUMENTS, MYF(0), msg); |
| 1060 | |||
| 1061 | 16 | return; | |
| 1062 | } | ||
| 1063 | |||
| 1064 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 35 times.
|
59 | if (dblwr::Mode::is_same(new_value)) { |
| 1065 | 24 | return; | |
| 1066 | } | ||
| 1067 | |||
| 1068 | /* Handle DETECT_AND_RECOVER to DETECT_ONLY | ||
| 1069 | 1. Check if DETECT_ONLY setup is already initalized. If not, intialize | ||
| 1070 | DETECT_ONLY files and structures. | ||
| 1071 | 2. Flush the partially filled dblwr buffers. */ | ||
| 1072 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 18 times.
|
35 | if (dblwr::Mode::is_reduced_low(new_value)) { |
| 1073 | 17 | dberr_t err = dblwr::enable_reduced(); | |
| 1074 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (err != DB_SUCCESS) { |
| 1075 | char msg[FN_REFLEN]; | ||
| 1076 | ✗ | snprintf(msg, sizeof(msg), | |
| 1077 | "InnoDB: cannot change doublewrite mode to %s." | ||
| 1078 | " Please check if doublewrite directory is writable" | ||
| 1079 | " Error code: %d", | ||
| 1080 | dblwr::Mode::to_string(new_value), err); | ||
| 1081 | ✗ | my_error(ER_WRONG_ARGUMENTS, MYF(0), msg); | |
| 1082 | ✗ | return; | |
| 1083 | } | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /* Handle DETECT_ONLY to DETECT_AND_RECOVER. | ||
| 1087 | 1. Flush partially filled reduced dblwr buffers */ | ||
| 1088 | 35 | dblwr::force_flush_all(); | |
| 1089 | |||
| 1090 | 35 | *static_cast<ulong *>(var_ptr) = *static_cast<const ulong *>(save); | |
| 1091 | } | ||
| 1092 | |||
| 1093 | /** Set up InnoDB API callback function array */ | ||
| 1094 | /* | ||
| 1095 | Generates array elements which look like: | ||
| 1096 | (ib_cb_t)ib_cursor_open_table, | ||
| 1097 | for each api function. | ||
| 1098 | */ | ||
| 1099 | #define INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM(stem) (ib_cb_t) ib_##stem, | ||
| 1100 | |||
| 1101 | static ib_cb_t innodb_api_cb[] = { | ||
| 1102 | FOR_EACH_API_METHOD_NAME_STEM(INNODB_API_CB_ARRAY_ELEMENT_TRANSFORM)}; | ||
| 1103 | |||
| 1104 | static int innodb_check_session_admin(THD *thd, SYS_VAR *self, void *save, | ||
| 1105 | struct st_mysql_value *value); | ||
| 1106 | |||
| 1107 | /**Check whether valid argument given to innobase_*_stopword_table. | ||
| 1108 | This function is registered as a callback with MySQL. | ||
| 1109 | @param[in] thd thread handle | ||
| 1110 | @param[in] var pointer to system variable | ||
| 1111 | @param[out] save immediate result for update function | ||
| 1112 | @param[in] value incoming string | ||
| 1113 | @return 0 for valid stopword table */ | ||
| 1114 | static int innodb_stopword_table_validate(THD *thd, SYS_VAR *var, void *save, | ||
| 1115 | struct st_mysql_value *value); | ||
| 1116 | |||
| 1117 | /** Validate passed-in "value" is a valid directory name. | ||
| 1118 | This function is registered as a callback with MySQL. | ||
| 1119 | @param[in,out] thd thread handle | ||
| 1120 | @param[out] save immediate result for update | ||
| 1121 | @param[in] value incoming string | ||
| 1122 | @return 0 for valid name */ | ||
| 1123 | 17 | static int innodb_tmpdir_validate(THD *thd, SYS_VAR *, void *save, | |
| 1124 | struct st_mysql_value *value) { | ||
| 1125 | char *alter_tmp_dir; | ||
| 1126 | char *innodb_tmp_dir; | ||
| 1127 | char buff[OS_FILE_MAX_PATH]; | ||
| 1128 | 17 | int len = sizeof(buff); | |
| 1129 | char tmp_abs_path[FN_REFLEN + 2]; | ||
| 1130 | |||
| 1131 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | ut_ad(save != nullptr); |
| 1132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | ut_ad(value != nullptr); |
| 1133 | |||
| 1134 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
17 | if (check_global_access(thd, FILE_ACL)) { |
| 1135 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 1136 | "InnoDB: FILE Permissions required"); | ||
| 1137 | ✗ | *static_cast<const char **>(save) = nullptr; | |
| 1138 | ✗ | return (1); | |
| 1139 | } | ||
| 1140 | |||
| 1141 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | alter_tmp_dir = (char *)value->val_str(value, buff, &len); |
| 1142 | |||
| 1143 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8 times.
|
17 | if (!alter_tmp_dir) { |
| 1144 | 9 | *static_cast<const char **>(save) = alter_tmp_dir; | |
| 1145 | 9 | return (0); | |
| 1146 | } | ||
| 1147 | |||
| 1148 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (strlen(alter_tmp_dir) > FN_REFLEN) { |
| 1149 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, |
| 1150 | "Path length should not exceed %d bytes", FN_REFLEN); | ||
| 1151 | 1 | *static_cast<const char **>(save) = nullptr; | |
| 1152 | 1 | return (1); | |
| 1153 | } | ||
| 1154 | |||
| 1155 | 7 | Fil_path::normalize(alter_tmp_dir); | |
| 1156 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_realpath(tmp_abs_path, alter_tmp_dir, 0); |
| 1157 | 7 | size_t tmp_abs_len = strlen(tmp_abs_path); | |
| 1158 | |||
| 1159 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
|
7 | if (my_access(tmp_abs_path, F_OK)) { |
| 1160 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, |
| 1161 | "InnoDB: Path doesn't exist."); | ||
| 1162 | 2 | *static_cast<const char **>(save) = nullptr; | |
| 1163 | 2 | return (1); | |
| 1164 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | } else if (my_access(tmp_abs_path, R_OK | W_OK)) { |
| 1165 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 1166 | "InnoDB: Server doesn't have permission in " | ||
| 1167 | "the given location."); | ||
| 1168 | ✗ | *static_cast<const char **>(save) = nullptr; | |
| 1169 | ✗ | return (1); | |
| 1170 | } | ||
| 1171 | |||
| 1172 | MY_STAT stat_info_dir; | ||
| 1173 | |||
| 1174 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) { |
| 1175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) { |
| 1176 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 1177 | "Given path is not a directory. "); | ||
| 1178 | ✗ | *static_cast<const char **>(save) = nullptr; | |
| 1179 | ✗ | return (1); | |
| 1180 | } | ||
| 1181 | } | ||
| 1182 | |||
| 1183 |
3/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
|
5 | if (!is_mysql_datadir_path(tmp_abs_path)) { |
| 1184 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, |
| 1185 | "InnoDB: Path location should not be same as " | ||
| 1186 | "mysql data directory location."); | ||
| 1187 | 1 | *static_cast<const char **>(save) = nullptr; | |
| 1188 | 1 | return (1); | |
| 1189 | } | ||
| 1190 | |||
| 1191 | innodb_tmp_dir = | ||
| 1192 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | static_cast<char *>(thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1)); |
| 1193 | 4 | *static_cast<const char **>(save) = innodb_tmp_dir; | |
| 1194 | 4 | return (0); | |
| 1195 | } | ||
| 1196 | |||
| 1197 | /** Empty free list algorithm. | ||
| 1198 | Checks if buffer pool is big enough to enable backoff algorithm. | ||
| 1199 | InnoDB empty free list algorithm backoff requires free pages | ||
| 1200 | from LRU for the best performance. | ||
| 1201 | buf_LRU_buf_pool_running_out cancels query if 1/4 of | ||
| 1202 | buffer pool belongs to LRU or freelist. | ||
| 1203 | At the same time buf_flush_LRU_list_batch | ||
| 1204 | keeps up to BUF_LRU_MIN_LEN in LRU. | ||
| 1205 | In order to avoid deadlock backoff requires buffer pool | ||
| 1206 | to be at least 4*BUF_LRU_MIN_LEN, | ||
| 1207 | but flush peformance is bad because of trashing | ||
| 1208 | and additional BUF_LRU_MIN_LEN pages are requested. | ||
| 1209 | @param[in] algorithm desired algorithm from srv_empty_free_list_t | ||
| 1210 | @param[in] new_buf_pool_sz requested buffer pool size | ||
| 1211 | @return true if it's possible to enable backoff. */ | ||
| 1212 | 12067 | static bool innodb_empty_free_list_algorithm_allowed( | |
| 1213 | srv_empty_free_list_t algorithm, long long new_buf_pool_sz = 0) { | ||
| 1214 |
2/2✓ Branch 0 taken 12038 times.
✓ Branch 1 taken 29 times.
|
12067 | if (!new_buf_pool_sz) new_buf_pool_sz = srv_buf_pool_size; |
| 1215 | |||
| 1216 | 12067 | const long long buf_pool_pages = | |
| 1217 | 12067 | new_buf_pool_sz / srv_page_size / srv_buf_pool_instances; | |
| 1218 | |||
| 1219 |
4/4✓ Branch 0 taken 53 times.
✓ Branch 1 taken 12014 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 5 times.
|
12067 | return (buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1) || |
| 1220 | 12067 | algorithm != SRV_EMPTY_FREE_LIST_BACKOFF); | |
| 1221 | } | ||
| 1222 | |||
| 1223 | /** Gets field offset for a field in a table. | ||
| 1224 | @param[in] table MySQL table object | ||
| 1225 | @param[in] field MySQL field object | ||
| 1226 | @return offset */ | ||
| 1227 | static inline uint get_field_offset(const TABLE *table, const Field *field); | ||
| 1228 | |||
| 1229 | static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG, | ||
| 1230 | "Enable InnoDB locking in LOCK TABLES", | ||
| 1231 | /* check_func */ nullptr, /* update_func */ nullptr, | ||
| 1232 | /* default */ true); | ||
| 1233 | |||
| 1234 | static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG, | ||
| 1235 | "Use strict mode when evaluating create options.", | ||
| 1236 | innodb_check_session_admin, nullptr, true); | ||
| 1237 | |||
| 1238 | static MYSQL_THDVAR_BOOL(ft_enable_stopword, | ||
| 1239 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1240 | "Create FTS index with stopword.", nullptr, nullptr, | ||
| 1241 | /* default */ true); | ||
| 1242 | |||
| 1243 | static MYSQL_THDVAR_ULONG(lock_wait_timeout, | ||
| 1244 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1245 | "Timeout in seconds an InnoDB transaction may wait " | ||
| 1246 | "for a lock before being rolled back. Values above " | ||
| 1247 | "100000000 disable the timeout.", | ||
| 1248 | nullptr, nullptr, 50, 1, 1024 * 1024 * 1024, 0); | ||
| 1249 | |||
| 1250 | static MYSQL_THDVAR_STR( | ||
| 1251 | ft_user_stopword_table, | ||
| 1252 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1253 | "User supplied stopword table name, effective in the session level.", | ||
| 1254 | innodb_stopword_table_validate, nullptr, nullptr); | ||
| 1255 | |||
| 1256 | static MYSQL_THDVAR_STR(tmpdir, | ||
| 1257 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | | ||
| 1258 | PLUGIN_VAR_HINTUPDATEABLE, | ||
| 1259 | "Directory for temporary non-tablespace files.", | ||
| 1260 | innodb_tmpdir_validate, nullptr, nullptr); | ||
| 1261 | |||
| 1262 | static MYSQL_THDVAR_BOOL(ft_ignore_stopwords, PLUGIN_VAR_OPCMDARG, | ||
| 1263 | "Instruct FTS to ignore stopwords.", nullptr, nullptr, | ||
| 1264 | false); | ||
| 1265 | |||
| 1266 | static MYSQL_THDVAR_ULONG(parallel_read_threads, PLUGIN_VAR_RQCMDARG, | ||
| 1267 | "Number of threads to do parallel read.", nullptr, | ||
| 1268 | nullptr, 4, /* Default. */ | ||
| 1269 | 1, /* Minimum. */ | ||
| 1270 | Parallel_reader::MAX_THREADS, /* Maxumum. */ | ||
| 1271 | 0); | ||
| 1272 | |||
| 1273 | static MYSQL_THDVAR_ULONG(ddl_buffer_size, PLUGIN_VAR_RQCMDARG, | ||
| 1274 | "Maximum size of memory to use (in bytes) for DDL.", | ||
| 1275 | nullptr, nullptr, 1048576, /* Default. */ | ||
| 1276 | 65536, /* Minimum. */ | ||
| 1277 | 4294967295, 0); /* Maximum. */ | ||
| 1278 | |||
| 1279 | static MYSQL_THDVAR_ULONG(ddl_threads, PLUGIN_VAR_RQCMDARG, | ||
| 1280 | "Maximum number of threads to use for DDL.", nullptr, | ||
| 1281 | nullptr, 4, /* Default. */ | ||
| 1282 | 1, /* Minimum. */ | ||
| 1283 | 64, 0); /* Maximum. */ | ||
| 1284 | |||
| 1285 | static SHOW_VAR innodb_status_variables[] = { | ||
| 1286 | {"background_log_sync", (char *)&export_vars.innodb_background_log_sync, | ||
| 1287 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1288 | {"buffer_pool_dump_status", | ||
| 1289 | (char *)&export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR, | ||
| 1290 | SHOW_SCOPE_GLOBAL}, | ||
| 1291 | {"buffer_pool_load_status", | ||
| 1292 | (char *)&export_vars.innodb_buffer_pool_load_status, SHOW_CHAR, | ||
| 1293 | SHOW_SCOPE_GLOBAL}, | ||
| 1294 | {"buffer_pool_resize_status", | ||
| 1295 | (char *)&export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR, | ||
| 1296 | SHOW_SCOPE_GLOBAL}, | ||
| 1297 | {"buffer_pool_pages_data", | ||
| 1298 | (char *)&export_vars.innodb_buffer_pool_pages_data, SHOW_LONG, | ||
| 1299 | SHOW_SCOPE_GLOBAL}, | ||
| 1300 | {"buffer_pool_bytes_data", | ||
| 1301 | (char *)&export_vars.innodb_buffer_pool_bytes_data, SHOW_LONG, | ||
| 1302 | SHOW_SCOPE_GLOBAL}, | ||
| 1303 | {"buffer_pool_pages_dirty", | ||
| 1304 | (char *)&export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG, | ||
| 1305 | SHOW_SCOPE_GLOBAL}, | ||
| 1306 | {"buffer_pool_bytes_dirty", | ||
| 1307 | (char *)&export_vars.innodb_buffer_pool_bytes_dirty, SHOW_LONG, | ||
| 1308 | SHOW_SCOPE_GLOBAL}, | ||
| 1309 | {"buffer_pool_pages_flushed", | ||
| 1310 | (char *)&export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG, | ||
| 1311 | SHOW_SCOPE_GLOBAL}, | ||
| 1312 | {"buffer_pool_pages_free", | ||
| 1313 | (char *)&export_vars.innodb_buffer_pool_pages_free, SHOW_LONG, | ||
| 1314 | SHOW_SCOPE_GLOBAL}, | ||
| 1315 | #ifdef UNIV_DEBUG | ||
| 1316 | {"buffer_pool_pages_latched", | ||
| 1317 | (char *)&export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG, | ||
| 1318 | SHOW_SCOPE_GLOBAL}, | ||
| 1319 | #endif /* UNIV_DEBUG */ | ||
| 1320 | {"buffer_pool_pages_LRU_flushed", | ||
| 1321 | (char *)&export_vars.innodb_buffer_pool_pages_LRU_flushed, SHOW_LONG, | ||
| 1322 | SHOW_SCOPE_GLOBAL}, | ||
| 1323 | {"buffer_pool_pages_made_not_young", | ||
| 1324 | (char *)&export_vars.innodb_buffer_pool_pages_made_not_young, SHOW_LONG, | ||
| 1325 | SHOW_SCOPE_GLOBAL}, | ||
| 1326 | {"buffer_pool_pages_made_young", | ||
| 1327 | (char *)&export_vars.innodb_buffer_pool_pages_made_young, SHOW_LONG, | ||
| 1328 | SHOW_SCOPE_GLOBAL}, | ||
| 1329 | {"buffer_pool_pages_misc", | ||
| 1330 | (char *)&export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG, | ||
| 1331 | SHOW_SCOPE_GLOBAL}, | ||
| 1332 | {"buffer_pool_pages_old", (char *)&export_vars.innodb_buffer_pool_pages_old, | ||
| 1333 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1334 | {"buffer_pool_pages_total", | ||
| 1335 | (char *)&export_vars.innodb_buffer_pool_pages_total, SHOW_LONG, | ||
| 1336 | SHOW_SCOPE_GLOBAL}, | ||
| 1337 | {"buffer_pool_read_ahead_rnd", | ||
| 1338 | (char *)&export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG, | ||
| 1339 | SHOW_SCOPE_GLOBAL}, | ||
| 1340 | {"buffer_pool_read_ahead", | ||
| 1341 | (char *)&export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG, | ||
| 1342 | SHOW_SCOPE_GLOBAL}, | ||
| 1343 | {"buffer_pool_read_ahead_evicted", | ||
| 1344 | (char *)&export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_LONG, | ||
| 1345 | SHOW_SCOPE_GLOBAL}, | ||
| 1346 | {"buffer_pool_read_requests", | ||
| 1347 | (char *)&export_vars.innodb_buffer_pool_read_requests, SHOW_LONG, | ||
| 1348 | SHOW_SCOPE_GLOBAL}, | ||
| 1349 | {"buffer_pool_reads", (char *)&export_vars.innodb_buffer_pool_reads, | ||
| 1350 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1351 | {"buffer_pool_wait_free", (char *)&export_vars.innodb_buffer_pool_wait_free, | ||
| 1352 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1353 | {"buffer_pool_write_requests", | ||
| 1354 | (char *)&export_vars.innodb_buffer_pool_write_requests, SHOW_LONG, | ||
| 1355 | SHOW_SCOPE_GLOBAL}, | ||
| 1356 | {"checkpoint_age", (char *)&export_vars.innodb_checkpoint_age, SHOW_LONG, | ||
| 1357 | SHOW_SCOPE_GLOBAL}, | ||
| 1358 | {"checkpoint_max_age", (char *)&export_vars.innodb_checkpoint_max_age, | ||
| 1359 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1360 | {"data_fsyncs", (char *)&export_vars.innodb_data_fsyncs, SHOW_LONG, | ||
| 1361 | SHOW_SCOPE_GLOBAL}, | ||
| 1362 | {"data_pending_fsyncs", (char *)&export_vars.innodb_data_pending_fsyncs, | ||
| 1363 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1364 | {"data_pending_reads", (char *)&export_vars.innodb_data_pending_reads, | ||
| 1365 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1366 | {"data_pending_writes", (char *)&export_vars.innodb_data_pending_writes, | ||
| 1367 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1368 | {"data_read", (char *)&export_vars.innodb_data_read, SHOW_LONG, | ||
| 1369 | SHOW_SCOPE_GLOBAL}, | ||
| 1370 | {"data_reads", (char *)&export_vars.innodb_data_reads, SHOW_LONG, | ||
| 1371 | SHOW_SCOPE_GLOBAL}, | ||
| 1372 | {"data_writes", (char *)&export_vars.innodb_data_writes, SHOW_LONG, | ||
| 1373 | SHOW_SCOPE_GLOBAL}, | ||
| 1374 | {"data_written", (char *)&export_vars.innodb_data_written, SHOW_LONG, | ||
| 1375 | SHOW_SCOPE_GLOBAL}, | ||
| 1376 | {"dblwr_pages_written", (char *)&export_vars.innodb_dblwr_pages_written, | ||
| 1377 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1378 | {"dblwr_writes", (char *)&export_vars.innodb_dblwr_writes, SHOW_LONG, | ||
| 1379 | SHOW_SCOPE_GLOBAL}, | ||
| 1380 | {"ibuf_free_list", (char *)&export_vars.innodb_ibuf_free_list, SHOW_LONG, | ||
| 1381 | SHOW_SCOPE_GLOBAL}, | ||
| 1382 | {"ibuf_segment_size", (char *)&export_vars.innodb_ibuf_segment_size, | ||
| 1383 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1384 | {"redo_log_read_only", (char *)&export_vars.innodb_redo_log_read_only, | ||
| 1385 | SHOW_BOOL, SHOW_SCOPE_GLOBAL}, | ||
| 1386 | {"redo_log_uuid", (char *)&export_vars.innodb_redo_log_uuid, SHOW_LONGLONG, | ||
| 1387 | SHOW_SCOPE_GLOBAL}, | ||
| 1388 | {"redo_log_checkpoint_lsn", | ||
| 1389 | (char *)&export_vars.innodb_redo_log_checkpoint_lsn, SHOW_LONGLONG, | ||
| 1390 | SHOW_SCOPE_GLOBAL}, | ||
| 1391 | {"redo_log_current_lsn", (char *)&export_vars.innodb_redo_log_current_lsn, | ||
| 1392 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1393 | {"redo_log_flushed_to_disk_lsn", | ||
| 1394 | (char *)&export_vars.innodb_redo_log_flushed_to_disk_lsn, SHOW_LONGLONG, | ||
| 1395 | SHOW_SCOPE_GLOBAL}, | ||
| 1396 | {"redo_log_logical_size", (char *)&export_vars.innodb_redo_log_logical_size, | ||
| 1397 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1398 | {"redo_log_physical_size", | ||
| 1399 | (char *)&export_vars.innodb_redo_log_physical_size, SHOW_LONGLONG, | ||
| 1400 | SHOW_SCOPE_GLOBAL}, | ||
| 1401 | {"redo_log_capacity_resized", | ||
| 1402 | (char *)&export_vars.innodb_redo_log_capacity_resized, SHOW_LONGLONG, | ||
| 1403 | SHOW_SCOPE_GLOBAL}, | ||
| 1404 | {"redo_log_resize_status", | ||
| 1405 | (char *)&export_vars.innodb_redo_log_resize_status, SHOW_CHAR, | ||
| 1406 | SHOW_SCOPE_GLOBAL}, | ||
| 1407 | {"log_waits", (char *)&export_vars.innodb_log_waits, SHOW_LONG, | ||
| 1408 | SHOW_SCOPE_GLOBAL}, | ||
| 1409 | {"log_write_requests", (char *)&export_vars.innodb_log_write_requests, | ||
| 1410 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1411 | {"log_writes", (char *)&export_vars.innodb_log_writes, SHOW_LONG, | ||
| 1412 | SHOW_SCOPE_GLOBAL}, | ||
| 1413 | {"lsn_current", (char *)&export_vars.innodb_lsn_current, SHOW_LONGLONG, | ||
| 1414 | SHOW_SCOPE_GLOBAL}, | ||
| 1415 | {"lsn_flushed", (char *)&export_vars.innodb_lsn_flushed, SHOW_LONGLONG, | ||
| 1416 | SHOW_SCOPE_GLOBAL}, | ||
| 1417 | {"lsn_last_checkpoint", (char *)&export_vars.innodb_lsn_last_checkpoint, | ||
| 1418 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1419 | {"master_thread_active_loops", | ||
| 1420 | (char *)&export_vars.innodb_master_thread_active_loops, SHOW_LONG, | ||
| 1421 | SHOW_SCOPE_GLOBAL}, | ||
| 1422 | {"master_thread_idle_loops", | ||
| 1423 | (char *)&export_vars.innodb_master_thread_idle_loops, SHOW_LONG, | ||
| 1424 | SHOW_SCOPE_GLOBAL}, | ||
| 1425 | {"max_trx_id", (char *)&export_vars.innodb_max_trx_id, SHOW_LONGLONG, | ||
| 1426 | SHOW_SCOPE_GLOBAL}, | ||
| 1427 | {"oldest_view_low_limit_trx_id", | ||
| 1428 | (char *)&export_vars.innodb_oldest_view_low_limit_trx_id, SHOW_LONGLONG, | ||
| 1429 | SHOW_SCOPE_GLOBAL}, | ||
| 1430 | {"os_log_fsyncs", (char *)&export_vars.innodb_os_log_fsyncs, SHOW_LONG, | ||
| 1431 | SHOW_SCOPE_GLOBAL}, | ||
| 1432 | {"os_log_pending_fsyncs", (char *)&export_vars.innodb_os_log_pending_fsyncs, | ||
| 1433 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1434 | {"os_log_pending_writes", (char *)&export_vars.innodb_os_log_pending_writes, | ||
| 1435 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1436 | {"os_log_written", (char *)&export_vars.innodb_os_log_written, | ||
| 1437 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1438 | {"page_size", (char *)&export_vars.innodb_page_size, SHOW_LONG, | ||
| 1439 | SHOW_SCOPE_GLOBAL}, | ||
| 1440 | {"pages_created", (char *)&export_vars.innodb_pages_created, SHOW_LONG, | ||
| 1441 | SHOW_SCOPE_GLOBAL}, | ||
| 1442 | {"pages_read", (char *)&export_vars.innodb_pages_read, SHOW_LONG, | ||
| 1443 | SHOW_SCOPE_GLOBAL}, | ||
| 1444 | {"pages0_read", (char *)&export_vars.innodb_page0_read, SHOW_LONG, | ||
| 1445 | SHOW_SCOPE_GLOBAL}, | ||
| 1446 | {"pages_written", (char *)&export_vars.innodb_pages_written, SHOW_LONG, | ||
| 1447 | SHOW_SCOPE_GLOBAL}, | ||
| 1448 | {"purge_trx_id", (char *)&export_vars.innodb_purge_trx_id, SHOW_LONGLONG, | ||
| 1449 | SHOW_SCOPE_GLOBAL}, | ||
| 1450 | {"purge_undo_no", (char *)&export_vars.innodb_purge_undo_no, SHOW_LONGLONG, | ||
| 1451 | SHOW_SCOPE_GLOBAL}, | ||
| 1452 | {"redo_log_enabled", (char *)&export_vars.innodb_redo_log_enabled, | ||
| 1453 | SHOW_BOOL, SHOW_SCOPE_GLOBAL}, | ||
| 1454 | {"row_lock_current_waits", | ||
| 1455 | (char *)&export_vars.innodb_row_lock_current_waits, SHOW_LONG, | ||
| 1456 | SHOW_SCOPE_GLOBAL}, | ||
| 1457 | {"row_lock_time", (char *)&export_vars.innodb_row_lock_time, SHOW_LONGLONG, | ||
| 1458 | SHOW_SCOPE_GLOBAL}, | ||
| 1459 | {"row_lock_time_avg", (char *)&export_vars.innodb_row_lock_time_avg, | ||
| 1460 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1461 | {"row_lock_time_max", (char *)&export_vars.innodb_row_lock_time_max, | ||
| 1462 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1463 | {"row_lock_waits", (char *)&export_vars.innodb_row_lock_waits, SHOW_LONG, | ||
| 1464 | SHOW_SCOPE_GLOBAL}, | ||
| 1465 | {"rows_deleted", (char *)&export_vars.innodb_rows_deleted, SHOW_LONG, | ||
| 1466 | SHOW_SCOPE_GLOBAL}, | ||
| 1467 | {"rows_inserted", (char *)&export_vars.innodb_rows_inserted, SHOW_LONG, | ||
| 1468 | SHOW_SCOPE_GLOBAL}, | ||
| 1469 | {"rows_read", (char *)&export_vars.innodb_rows_read, SHOW_LONG, | ||
| 1470 | SHOW_SCOPE_GLOBAL}, | ||
| 1471 | {"rows_updated", (char *)&export_vars.innodb_rows_updated, SHOW_LONG, | ||
| 1472 | SHOW_SCOPE_GLOBAL}, | ||
| 1473 | {"system_rows_deleted", (char *)&export_vars.innodb_system_rows_deleted, | ||
| 1474 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1475 | {"system_rows_inserted", (char *)&export_vars.innodb_system_rows_inserted, | ||
| 1476 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1477 | {"system_rows_read", (char *)&export_vars.innodb_system_rows_read, | ||
| 1478 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1479 | {"system_rows_updated", (char *)&export_vars.innodb_system_rows_updated, | ||
| 1480 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1481 | {"sampled_pages_read", (char *)&export_vars.innodb_sampled_pages_read, | ||
| 1482 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1483 | {"sampled_pages_skipped", (char *)&export_vars.innodb_sampled_pages_skipped, | ||
| 1484 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1485 | {"num_open_files", (char *)&export_vars.innodb_num_open_files, SHOW_LONG, | ||
| 1486 | SHOW_SCOPE_GLOBAL}, | ||
| 1487 | {"truncated_status_writes", | ||
| 1488 | (char *)&export_vars.innodb_truncated_status_writes, SHOW_LONG, | ||
| 1489 | SHOW_SCOPE_GLOBAL}, | ||
| 1490 | {"undo_tablespaces_total", | ||
| 1491 | (char *)&export_vars.innodb_undo_tablespaces_total, SHOW_LONG, | ||
| 1492 | SHOW_SCOPE_GLOBAL}, | ||
| 1493 | {"undo_tablespaces_implicit", | ||
| 1494 | (char *)&export_vars.innodb_undo_tablespaces_implicit, SHOW_LONG, | ||
| 1495 | SHOW_SCOPE_GLOBAL}, | ||
| 1496 | {"undo_tablespaces_explicit", | ||
| 1497 | (char *)&export_vars.innodb_undo_tablespaces_explicit, SHOW_LONG, | ||
| 1498 | SHOW_SCOPE_GLOBAL}, | ||
| 1499 | {"undo_tablespaces_active", | ||
| 1500 | (char *)&export_vars.innodb_undo_tablespaces_active, SHOW_LONG, | ||
| 1501 | SHOW_SCOPE_GLOBAL}, | ||
| 1502 | #ifdef UNIV_DEBUG | ||
| 1503 | {"purge_trx_id_age", (char *)&export_vars.innodb_purge_trx_id_age, | ||
| 1504 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1505 | {"purge_view_trx_id_age", (char *)&export_vars.innodb_purge_view_trx_id_age, | ||
| 1506 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1507 | {"ahi_drop_lookups", (char *)&export_vars.innodb_ahi_drop_lookups, | ||
| 1508 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1509 | #endif /* UNIV_DEBUG */ | ||
| 1510 | {"secondary_index_triggered_cluster_reads", | ||
| 1511 | (char *)&export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG, | ||
| 1512 | SHOW_SCOPE_GLOBAL}, | ||
| 1513 | {"secondary_index_triggered_cluster_reads_avoided", | ||
| 1514 | (char *)&export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG, | ||
| 1515 | SHOW_SCOPE_GLOBAL}, | ||
| 1516 | {"buffered_aio_submitted", | ||
| 1517 | (char *)&export_vars.innodb_buffered_aio_submitted, SHOW_LONG, | ||
| 1518 | SHOW_SCOPE_GLOBAL}, | ||
| 1519 | |||
| 1520 | {"scan_pages_contiguous", | ||
| 1521 | (char *)&export_vars.innodb_fragmentation_stats.scan_pages_contiguous, | ||
| 1522 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1523 | {"scan_pages_disjointed", | ||
| 1524 | (char *)&export_vars.innodb_fragmentation_stats.scan_pages_disjointed, | ||
| 1525 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1526 | {"scan_pages_total_seek_distance", | ||
| 1527 | (char *)&export_vars.innodb_fragmentation_stats | ||
| 1528 | .scan_pages_total_seek_distance, | ||
| 1529 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1530 | {"scan_data_size", | ||
| 1531 | (char *)&export_vars.innodb_fragmentation_stats.scan_data_size, SHOW_LONG, | ||
| 1532 | SHOW_SCOPE_GLOBAL}, | ||
| 1533 | {"scan_deleted_recs_size", | ||
| 1534 | (char *)&export_vars.innodb_fragmentation_stats.scan_deleted_recs_size, | ||
| 1535 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1536 | {"encryption_n_merge_blocks_encrypted", | ||
| 1537 | (char *)&export_vars.innodb_n_merge_blocks_encrypted, SHOW_LONGLONG, | ||
| 1538 | SHOW_SCOPE_GLOBAL}, | ||
| 1539 | {"encryption_n_merge_blocks_decrypted", | ||
| 1540 | (char *)&export_vars.innodb_n_merge_blocks_decrypted, SHOW_LONGLONG, | ||
| 1541 | SHOW_SCOPE_GLOBAL}, | ||
| 1542 | {"encryption_n_rowlog_blocks_encrypted", | ||
| 1543 | (char *)&export_vars.innodb_n_rowlog_blocks_encrypted, SHOW_LONGLONG, | ||
| 1544 | SHOW_SCOPE_GLOBAL}, | ||
| 1545 | {"encryption_n_rowlog_blocks_decrypted", | ||
| 1546 | (char *)&export_vars.innodb_n_rowlog_blocks_decrypted, SHOW_LONGLONG, | ||
| 1547 | SHOW_SCOPE_GLOBAL}, | ||
| 1548 | {"encryption_redo_key_version", | ||
| 1549 | (char *)&export_vars.innodb_redo_key_version, SHOW_LONGLONG, | ||
| 1550 | SHOW_SCOPE_GLOBAL}, | ||
| 1551 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1552 | /* Encryption */ | ||
| 1553 | {"encryption_rotation_pages_read_from_cache", | ||
| 1554 | (char *)&export_vars.innodb_encryption_rotation_pages_read_from_cache, | ||
| 1555 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1556 | {"encryption_rotation_pages_read_from_disk", | ||
| 1557 | (char *)&export_vars.innodb_encryption_rotation_pages_read_from_disk, | ||
| 1558 | SHOW_LONG, SHOW_SCOPE_GLOBAL}, | ||
| 1559 | {"encryption_rotation_pages_modified", | ||
| 1560 | (char *)&export_vars.innodb_encryption_rotation_pages_modified, SHOW_LONG, | ||
| 1561 | SHOW_SCOPE_GLOBAL}, | ||
| 1562 | {"encryption_rotation_pages_flushed", | ||
| 1563 | (char *)&export_vars.innodb_encryption_rotation_pages_flushed, SHOW_LONG, | ||
| 1564 | SHOW_SCOPE_GLOBAL}, | ||
| 1565 | {"encryption_rotation_estimated_iops", | ||
| 1566 | (char *)&export_vars.innodb_encryption_rotation_estimated_iops, SHOW_LONG, | ||
| 1567 | SHOW_SCOPE_GLOBAL}, | ||
| 1568 | {"encryption_key_rotation_list_length", | ||
| 1569 | (char *)&export_vars.innodb_key_rotation_list_length, SHOW_LONGLONG, | ||
| 1570 | SHOW_SCOPE_GLOBAL}, | ||
| 1571 | {"num_pages_encrypted", (char *)&export_vars.innodb_pages_encrypted, | ||
| 1572 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1573 | {"num_pages_decrypted", (char *)&export_vars.innodb_pages_decrypted, | ||
| 1574 | SHOW_LONGLONG, SHOW_SCOPE_GLOBAL}, | ||
| 1575 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}}; | ||
| 1576 | |||
| 1577 | /** Handling the shared INNOBASE_SHARE structure that is needed to provide table | ||
| 1578 | locking. Register the table name if it doesn't exist in the hash table. */ | ||
| 1579 | static INNOBASE_SHARE *get_share( | ||
| 1580 | const char *table_name); /*!< in: table to lookup */ | ||
| 1581 | |||
| 1582 | /** Free the shared object that was registered with get_share(). */ | ||
| 1583 | static void free_share(INNOBASE_SHARE *share); /*!< in/own: share to free */ | ||
| 1584 | |||
| 1585 | /** Calls free_share and assign nullptr to share. | ||
| 1586 | @param[in,out] share table share to free */ | ||
| 1587 | 4434068 | static void free_share_and_nullify( | |
| 1588 | INNOBASE_SHARE **share) /*!< in/own: table share to free */ | ||
| 1589 | { | ||
| 1590 | 4434068 | free_share(*share); | |
| 1591 | 4434068 | *share = nullptr; | |
| 1592 | 4434068 | } | |
| 1593 | |||
| 1594 | /** Frees a possible InnoDB trx object associated with the current THD. | ||
| 1595 | @return 0 or error number */ | ||
| 1596 | static int innobase_close_connection( | ||
| 1597 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1598 | THD *thd); /*!< in: MySQL thread handle for | ||
| 1599 | which to close the connection */ | ||
| 1600 | |||
| 1601 | /** Cancel any pending lock request associated with the current THD. */ | ||
| 1602 | static void innobase_kill_connection( | ||
| 1603 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1604 | THD *thd); /*!< in: MySQL thread handle for | ||
| 1605 | which to close the connection */ | ||
| 1606 | |||
| 1607 | /** Commits a transaction in an InnoDB database or marks an SQL statement | ||
| 1608 | ended. | ||
| 1609 | @return 0 */ | ||
| 1610 | static int innobase_commit(handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1611 | THD *thd, /*!< in: MySQL thread handle of the | ||
| 1612 | user for whom the transaction should | ||
| 1613 | be committed */ | ||
| 1614 | bool commit_trx); /*!< in: true - commit transaction | ||
| 1615 | false - the current SQL statement | ||
| 1616 | ended */ | ||
| 1617 | |||
| 1618 | /** Rolls back a transaction to a savepoint. | ||
| 1619 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 1620 | given name */ | ||
| 1621 | static int innobase_rollback(handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1622 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 1623 | of the user whose transaction should | ||
| 1624 | be rolled back */ | ||
| 1625 | bool rollback_trx); /*!< in: true - rollback entire | ||
| 1626 | transaction false - rollback | ||
| 1627 | the current statement only */ | ||
| 1628 | |||
| 1629 | /** Rolls back a transaction to a savepoint. | ||
| 1630 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 1631 | given name */ | ||
| 1632 | static int innobase_rollback_to_savepoint( | ||
| 1633 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1634 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 1635 | the user whose XA transaction should | ||
| 1636 | be rolled back to savepoint */ | ||
| 1637 | void *savepoint); /*!< in: savepoint data */ | ||
| 1638 | |||
| 1639 | /** Check whether innodb state allows to safely release MDL locks after | ||
| 1640 | rollback to savepoint. | ||
| 1641 | @return true if it is safe, false if its not safe. */ | ||
| 1642 | static bool innobase_rollback_to_savepoint_can_release_mdl( | ||
| 1643 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1644 | THD *thd); /*!< in: handle to the MySQL thread of | ||
| 1645 | the user whose XA transaction should | ||
| 1646 | be rolled back to savepoint */ | ||
| 1647 | |||
| 1648 | /** Sets a transaction savepoint. | ||
| 1649 | @return always 0, that is, always succeeds */ | ||
| 1650 | static int innobase_savepoint( | ||
| 1651 | handlerton *hton, /*!< in/out: InnoDB handlerton */ | ||
| 1652 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 1653 | the user's XA transaction for which | ||
| 1654 | we need to take a savepoint */ | ||
| 1655 | void *savepoint); /*!< in: savepoint data */ | ||
| 1656 | |||
| 1657 | /** Release transaction savepoint name. | ||
| 1658 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 1659 | given name */ | ||
| 1660 | static int innobase_release_savepoint( | ||
| 1661 | handlerton *hton, /*!< in/out: handlerton for InnoDB */ | ||
| 1662 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 1663 | of the user whose transaction's | ||
| 1664 | savepoint should be released */ | ||
| 1665 | void *savepoint); /*!< in: savepoint data */ | ||
| 1666 | |||
| 1667 | /** Function for constructing an InnoDB table handler instance. | ||
| 1668 | @param[in,out] hton handlerton for InnoDB | ||
| 1669 | @param[in] table MySQL table | ||
| 1670 | @param[in] partitioned Indicates whether table is partitioned | ||
| 1671 | @param[in] mem_root memory context */ | ||
| 1672 | static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, | ||
| 1673 | bool partitioned, MEM_ROOT *mem_root); | ||
| 1674 | |||
| 1675 | /** Retrieve table satistics. | ||
| 1676 | @param[in] db_name database name | ||
| 1677 | @param[in] table_name table name | ||
| 1678 | @param[in] se_private_id The internal id of the table | ||
| 1679 | @param[in] ts_se_private_data Tablespace SE Private data | ||
| 1680 | @param[in] tbl_se_private_data Table SE private data | ||
| 1681 | @param[in] stat_flags flags used to retrieve specific stats | ||
| 1682 | @param[in,out] stats structure to save the | ||
| 1683 | retrieved statistics | ||
| 1684 | @return false on success, true on failure */ | ||
| 1685 | static bool innobase_get_table_statistics( | ||
| 1686 | const char *db_name, const char *table_name, dd::Object_id se_private_id, | ||
| 1687 | const dd::Properties &ts_se_private_data, | ||
| 1688 | const dd::Properties &tbl_se_private_data, uint stat_flags, | ||
| 1689 | ha_statistics *stats); | ||
| 1690 | |||
| 1691 | /** Retrieve index column cardinality. | ||
| 1692 | @param[in] db_name name of schema | ||
| 1693 | @param[in] table_name name of table | ||
| 1694 | @param[in] index_name name of index | ||
| 1695 | @param[in] index_ordinal_position position of index | ||
| 1696 | @param[in] column_ordinal_position position of column in index | ||
| 1697 | @param[in] se_private_id the internal id of the table | ||
| 1698 | @param[in,out] cardinality cardinality of index column | ||
| 1699 | @retval false success | ||
| 1700 | @retval true failure */ | ||
| 1701 | static bool innobase_get_index_column_cardinality( | ||
| 1702 | const char *db_name, const char *table_name, const char *index_name, | ||
| 1703 | uint index_ordinal_position, uint column_ordinal_position, | ||
| 1704 | dd::Object_id se_private_id, ulonglong *cardinality); | ||
| 1705 | |||
| 1706 | /** Retrieve ha_tablespace_statistics for the tablespace. | ||
| 1707 | |||
| 1708 | @param tablespace_name Tablespace_name | ||
| 1709 | @param file_name Data file name. | ||
| 1710 | @param ts_se_private_data Tablespace SE private data. | ||
| 1711 | @param[out] stats Contains tablespace | ||
| 1712 | statistics read from SE. | ||
| 1713 | @return false on success, true on failure */ | ||
| 1714 | static bool innobase_get_tablespace_statistics( | ||
| 1715 | const char *tablespace_name, const char *file_name, | ||
| 1716 | const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats); | ||
| 1717 | |||
| 1718 | static bool innobase_is_tablespace_keyring_pre_v3_encrypted( | ||
| 1719 | const dd::Tablespace &tablespace, int &error); | ||
| 1720 | /** Retrieve the tablespace type. | ||
| 1721 | |||
| 1722 | @param space Tablespace object. | ||
| 1723 | @param[out] space_type Tablespace category. | ||
| 1724 | @return false on success, true on failure */ | ||
| 1725 | static bool innobase_get_tablespace_type(const dd::Tablespace &space, | ||
| 1726 | Tablespace_type *space_type); | ||
| 1727 | |||
| 1728 | /** Get the tablespace type given the name. | ||
| 1729 | |||
| 1730 | @param[in] tablespace_name tablespace name | ||
| 1731 | @param[out] space_type type of space | ||
| 1732 | |||
| 1733 | @return Operation status. | ||
| 1734 | @retval false on success and true for failure. | ||
| 1735 | */ | ||
| 1736 | static bool innobase_get_tablespace_type_by_name(const char *tablespace_name, | ||
| 1737 | Tablespace_type *space_type); | ||
| 1738 | |||
| 1739 | /** Perform post-commit/rollback cleanup after DDL statement. | ||
| 1740 | @param[in,out] thd connection thread */ | ||
| 1741 | static void innobase_post_ddl(THD *thd); | ||
| 1742 | |||
| 1743 | /** Check if types of child and parent columns in foreign key are compatible. | ||
| 1744 | @param[in] child_column_type Child column type description. | ||
| 1745 | @param[in] parent_column_type Parent column type description. | ||
| 1746 | @param[in] check_charsets Indicates whether we need to check | ||
| 1747 | that charsets of string columns | ||
| 1748 | match. Which is true in most cases. | ||
| 1749 | @return True if types are compatible, False if not. */ | ||
| 1750 | static bool innodb_check_fk_column_compat( | ||
| 1751 | const Ha_fk_column_type *child_column_type, | ||
| 1752 | const Ha_fk_column_type *parent_column_type, bool check_charsets); | ||
| 1753 | |||
| 1754 | /** @brief Initialize the default value of innodb_commit_concurrency. | ||
| 1755 | |||
| 1756 | Once InnoDB is running, the innodb_commit_concurrency must not change | ||
| 1757 | from zero to nonzero. (Bug #42101) | ||
| 1758 | |||
| 1759 | The initial default value is 0, and without this extra initialization, | ||
| 1760 | SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter | ||
| 1761 | to 0, even if it was initially set to nonzero at the command line | ||
| 1762 | or configuration file. */ | ||
| 1763 | static void innobase_commit_concurrency_init_default(); | ||
| 1764 | |||
| 1765 | /** This function is used to prepare an X/Open XA distributed transaction. | ||
| 1766 | @return 0 or error number */ | ||
| 1767 | static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1768 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 1769 | the user whose XA transaction should | ||
| 1770 | be prepared */ | ||
| 1771 | bool all); /*!< in: true - prepare transaction | ||
| 1772 | false - the current SQL statement | ||
| 1773 | ended */ | ||
| 1774 | /** This function is used to recover X/Open XA distributed transactions. | ||
| 1775 | @return number of prepared transactions stored in xid_list */ | ||
| 1776 | static int innobase_xa_recover( | ||
| 1777 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1778 | XA_recover_txn *txn_list, /*!< in/out: prepared transactions */ | ||
| 1779 | uint len, /*!< in: number of slots in xid_list */ | ||
| 1780 | MEM_ROOT *mem_root); /*!< in: memory for table names */ | ||
| 1781 | /** Find prepared transactions that are marked as prepared in TC, for recovery | ||
| 1782 | purposes. | ||
| 1783 | @param[in] hton InnoDB handlerton | ||
| 1784 | @param[in,out] xa_list prepared transactions state | ||
| 1785 | @return 0 if successful or error number */ | ||
| 1786 | static int innobase_xa_recover_prepared_in_tc(handlerton *hton, | ||
| 1787 | Xa_state_list &xa_list); | ||
| 1788 | /** This function is used to commit one X/Open XA distributed transaction | ||
| 1789 | which is in the prepared state | ||
| 1790 | @return 0 or error number */ | ||
| 1791 | static xa_status_code innobase_commit_by_xid( | ||
| 1792 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1793 | XID *xid); /*!< in: X/Open XA transaction | ||
| 1794 | identification */ | ||
| 1795 | /** This function is used to rollback one X/Open XA distributed transaction | ||
| 1796 | which is in the prepared state | ||
| 1797 | @return 0 or error number */ | ||
| 1798 | static xa_status_code innobase_rollback_by_xid( | ||
| 1799 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 1800 | XID *xid); /*!< in: X/Open XA transaction | ||
| 1801 | identification */ | ||
| 1802 | /** This function is used to write mark an X/Open XA distributed transaction | ||
| 1803 | as been prepared in the server transaction coordinator | ||
| 1804 | @param[in] hton InnoDB handlerton | ||
| 1805 | @param[in] thd handle to the MySQL thread of the user whose XA transaction | ||
| 1806 | should be prepared | ||
| 1807 | @return 0 or error number */ | ||
| 1808 | static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd); | ||
| 1809 | /** Mark an X/Open XA distributed transaction | ||
| 1810 | as been prepared in the server transaction coordinator | ||
| 1811 | @param[in] hton InnoDB handlerton | ||
| 1812 | @param[in] xid X/Open XA transaction identification the MySQL thread of the | ||
| 1813 | user whosefo the XA transaction that should be prepared | ||
| 1814 | @return XA_OK or error number */ | ||
| 1815 | static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton, | ||
| 1816 | XID *xid); | ||
| 1817 | /** Checks if the file name is reserved in InnoDB. Currently | ||
| 1818 | redo log file names from the old redo format (ib_logfile*) | ||
| 1819 | are reserved. There is no need to reserve file names from the | ||
| 1820 | newer redo formats, because they start with '#'. | ||
| 1821 | @return true if the name is reserved | ||
| 1822 | @param[in] hton handlerton of InnoDB | ||
| 1823 | @param[in] name Name of the database */ | ||
| 1824 | static bool innobase_check_reserved_file_name(handlerton *hton, | ||
| 1825 | const char *name); | ||
| 1826 | /** Check tablespace name validity. | ||
| 1827 | @param[in] ts_cmd whether this is tablespace DDL or not | ||
| 1828 | @param[in] name name to check | ||
| 1829 | @retval false invalid name | ||
| 1830 | @retval true valid name */ | ||
| 1831 | static bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd, | ||
| 1832 | const char *name); | ||
| 1833 | |||
| 1834 | /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces. | ||
| 1835 | @param[in] hton Handlerton of InnoDB | ||
| 1836 | @param[in] thd Connection | ||
| 1837 | @param[in] alter_info Describes the command and how to do it. | ||
| 1838 | @param[in] old_ts_def Old version of dd::Tablespace object for the | ||
| 1839 | tablespace. | ||
| 1840 | @param[in,out] new_ts_def New version of dd::Tablespace object for the | ||
| 1841 | tablespace. Can be adjusted by SE. Changes will be persisted in the | ||
| 1842 | data-dictionary at statement commit. | ||
| 1843 | @return MySQL error code*/ | ||
| 1844 | static int innobase_alter_tablespace(handlerton *hton, THD *thd, | ||
| 1845 | st_alter_tablespace *alter_info, | ||
| 1846 | const dd::Tablespace *old_ts_def, | ||
| 1847 | dd::Tablespace *new_ts_def); | ||
| 1848 | |||
| 1849 | /** | ||
| 1850 | Get tablespace datafile name extension. | ||
| 1851 | */ | ||
| 1852 | static const char *innobase_get_tablespace_filename_ext(); | ||
| 1853 | |||
| 1854 | /** Free tablespace resources. */ | ||
| 1855 | 10407 | static void innodb_space_shutdown() { | |
| 1856 |
1/2✓ Branch 0 taken 10407 times.
✗ Branch 1 not taken.
|
10407 | DBUG_TRACE; |
| 1857 | |||
| 1858 |
1/2✓ Branch 0 taken 10407 times.
✗ Branch 1 not taken.
|
10407 | srv_sys_space.shutdown(); |
| 1859 |
2/2✓ Branch 0 taken 10306 times.
✓ Branch 1 taken 101 times.
|
10407 | if (srv_tmp_space.get_sanity_check_status()) { |
| 1860 |
1/2✓ Branch 0 taken 10306 times.
✗ Branch 1 not taken.
|
10306 | fil_space_close(srv_tmp_space.space_id()); |
| 1861 |
1/2✓ Branch 0 taken 10306 times.
✗ Branch 1 not taken.
|
10306 | srv_tmp_space.delete_files(); |
| 1862 | } | ||
| 1863 |
1/2✓ Branch 0 taken 10407 times.
✗ Branch 1 not taken.
|
10407 | srv_tmp_space.shutdown(); |
| 1864 | 10407 | } | |
| 1865 | |||
| 1866 | /** Shut down InnoDB after the Global Data Dictionary has been shut down. | ||
| 1867 | @see innodb_pre_dd_shutdown() | ||
| 1868 | @retval 0 always */ | ||
| 1869 | 10400 | static int innodb_shutdown(handlerton *, ha_panic_function) { | |
| 1870 |
1/2✓ Branch 0 taken 10400 times.
✗ Branch 1 not taken.
|
10400 | DBUG_TRACE; |
| 1871 | |||
| 1872 |
2/2✓ Branch 0 taken 10303 times.
✓ Branch 1 taken 97 times.
|
10400 | if (innodb_inited) { |
| 1873 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | log_pfs_delete_tables(); |
| 1874 | |||
| 1875 | 10303 | innodb_inited = false; | |
| 1876 | 10303 | ut::delete_(innobase_open_tables); | |
| 1877 | 10303 | innobase_open_tables = nullptr; | |
| 1878 | |||
| 1879 |
2/2✓ Branch 0 taken 10327 times.
✓ Branch 1 taken 10303 times.
|
20630 | for (auto file : innobase_sys_files) { |
| 1880 | 10327 | ut::delete_(file); | |
| 1881 | } | ||
| 1882 | 10303 | innobase_sys_files.clear(); | |
| 1883 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | innobase_sys_files.shrink_to_fit(); |
| 1884 | |||
| 1885 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | mutex_free(&master_key_id_mutex); |
| 1886 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | srv_shutdown(); |
| 1887 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | innodb_space_shutdown(); |
| 1888 | |||
| 1889 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | mysql_mutex_destroy(&innobase_share_mutex); |
| 1890 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | mysql_mutex_destroy(&commit_cond_m); |
| 1891 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | mysql_cond_destroy(&commit_cond); |
| 1892 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | mysql_mutex_destroy(&resume_encryption_cond_m); |
| 1893 |
1/2✓ Branch 0 taken 10303 times.
✗ Branch 1 not taken.
|
10303 | mysql_cond_destroy(&resume_encryption_cond); |
| 1894 | } | ||
| 1895 | |||
| 1896 |
1/2✓ Branch 0 taken 10400 times.
✗ Branch 1 not taken.
|
10400 | os_event_global_destroy(); |
| 1897 | |||
| 1898 |
1/2✓ Branch 0 taken 10400 times.
✗ Branch 1 not taken.
|
10400 | innobase::component_services::deinitialize_service_handles(); |
| 1899 | |||
| 1900 | 10400 | return 0; | |
| 1901 | 10400 | } | |
| 1902 | |||
| 1903 | /** Shut down all InnoDB background tasks that may access | ||
| 1904 | the Global Data Dictionary, before the Global Data Dictionary | ||
| 1905 | and the rest of InnoDB have been shut down. | ||
| 1906 | @see dd::shutdown() | ||
| 1907 | @see innodb_shutdown() */ | ||
| 1908 | 10418 | static void innodb_pre_dd_shutdown(handlerton *) { | |
| 1909 |
2/2✓ Branch 0 taken 10321 times.
✓ Branch 1 taken 97 times.
|
10418 | if (innodb_inited) { |
| 1910 | 10321 | srv_pre_dd_shutdown(); | |
| 1911 | } | ||
| 1912 | 10400 | } | |
| 1913 | |||
| 1914 | /** Stores the current binlog coordinates in the trx system header. | ||
| 1915 | @param[in] hton InnoDB handlerton | ||
| 1916 | @param[in] thd MySQL thrad handle */ | ||
| 1917 | static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept; | ||
| 1918 | |||
| 1919 | /** Creates an InnoDB transaction struct for the thd if it does not yet have | ||
| 1920 | one. Starts a new InnoDB transaction if a transaction is not yet started. And | ||
| 1921 | assigns a new snapshot for a consistent read if the transaction does not yet | ||
| 1922 | have one. | ||
| 1923 | @return 0 */ | ||
| 1924 | static int innobase_start_trx_and_assign_read_view( | ||
| 1925 | handlerton *hton, /* in: InnoDB handlerton */ | ||
| 1926 | THD *thd); /* in: MySQL thread handle of the | ||
| 1927 | user for whom the transaction should | ||
| 1928 | be committed */ | ||
| 1929 | |||
| 1930 | /** Creates an InnoDB transaction struct for the thd if it does not | ||
| 1931 | yet have one. Starts a new InnoDB transaction if a transaction is not | ||
| 1932 | yet started. And clones snapshot for a consistent read from another | ||
| 1933 | session, if it has one. | ||
| 1934 | @param[in] hton InnoDB handlerton | ||
| 1935 | @param[in] thd MySQL thread handle of the user for whom the | ||
| 1936 | transaction should be committed | ||
| 1937 | @param[in] from_thd MySQL thread handle of the user session from | ||
| 1938 | which the consistent read should be cloned | ||
| 1939 | @return 0 */ | ||
| 1940 | static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd, | ||
| 1941 | THD *from_thd); | ||
| 1942 | |||
| 1943 | /** Flush InnoDB redo logs to the file system. | ||
| 1944 | @param[in] hton InnoDB handlerton | ||
| 1945 | @param[in] binlog_group_flush true if we got invoked by binlog | ||
| 1946 | group commit during flush stage, false in other cases. | ||
| 1947 | @return false */ | ||
| 1948 | static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush); | ||
| 1949 | |||
| 1950 | /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the | ||
| 1951 | InnoDB Monitor to the client. | ||
| 1952 | @param[in] hton the innodb handlerton | ||
| 1953 | @param[in] thd the MySQL query thread of the caller | ||
| 1954 | @param[in] stat_print print function | ||
| 1955 | @return 0 on success */ | ||
| 1956 | static int innodb_show_status(handlerton *hton, THD *thd, | ||
| 1957 | stat_print_fn *stat_print); | ||
| 1958 | |||
| 1959 | /** Implements Log_resource lock. | ||
| 1960 | @param[in] hton the innodb handlerton | ||
| 1961 | @return false on success */ | ||
| 1962 | static bool innobase_lock_hton_log(handlerton *hton); | ||
| 1963 | |||
| 1964 | /** Implements Log_resource unlock. | ||
| 1965 | @param[in] hton the innodb handlerton | ||
| 1966 | @return false on success */ | ||
| 1967 | static bool innobase_unlock_hton_log(handlerton *hton); | ||
| 1968 | |||
| 1969 | /** Implements Log_resource collect_info. | ||
| 1970 | @param[in] hton the innodb handlerton | ||
| 1971 | @param[in] json the JSON dom to receive the log info | ||
| 1972 | @return false on success */ | ||
| 1973 | static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json); | ||
| 1974 | |||
| 1975 | /** Return 0 on success and non-zero on failure. Note: the bool return type | ||
| 1976 | seems to be abused here, should be an int. | ||
| 1977 | @param[in] hton the innodb handlerton | ||
| 1978 | @param[in] thd the MySQL query thread of the caller | ||
| 1979 | @param[in] stat_print print function | ||
| 1980 | @param[in] stat_type status to show */ | ||
| 1981 | static bool innobase_show_status(handlerton *hton, THD *thd, | ||
| 1982 | stat_print_fn *stat_print, | ||
| 1983 | enum ha_stat_type stat_type); | ||
| 1984 | |||
| 1985 | /** Parse and enable InnoDB monitor counters during server startup. | ||
| 1986 | User can enable monitor counters/groups by specifying | ||
| 1987 | "loose-innodb_monitor_enable = monitor_name1;monitor_name2..." | ||
| 1988 | in server configuration file or at the command line. */ | ||
| 1989 | static void innodb_enable_monitor_at_startup( | ||
| 1990 | char *str); /*!< in: monitor counter enable list */ | ||
| 1991 | |||
| 1992 | /** Fill handlerton based INFORMATION_SCHEMA tables. | ||
| 1993 | @param[in] hton (unused) Handle to the handlerton structure | ||
| 1994 | @param[in] thd Thread/connection descriptor | ||
| 1995 | @param[in,out] tables Information Schema tables to fill | ||
| 1996 | @param[in] idx_cond (unused) Intended for conditional pushdown | ||
| 1997 | @param[in] idx Table id that indicates which I_S table to fill | ||
| 1998 | @return Operation status */ | ||
| 1999 | 4 | static int innobase_fill_i_s_table(handlerton *hton [[maybe_unused]], | |
| 2000 | THD *thd [[maybe_unused]], | ||
| 2001 | TABLE_LIST *tables [[maybe_unused]], | ||
| 2002 | Item *idx_cond [[maybe_unused]], | ||
| 2003 | enum_schema_tables idx) { | ||
| 2004 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | assert(idx == SCH_TABLESPACES); |
| 2005 | |||
| 2006 | /** InnoDB does not implement I_S.TABLESPACES */ | ||
| 2007 | |||
| 2008 | 4 | return (0); | |
| 2009 | } | ||
| 2010 | |||
| 2011 | /** Store doc_id value into FTS_DOC_ID field | ||
| 2012 | @param[in,out] tbl table containing FULLTEXT index | ||
| 2013 | @param[in] doc_id FTS_DOC_ID value */ | ||
| 2014 | 134 | static void innobase_fts_store_docid(TABLE *tbl, ulonglong doc_id) { | |
| 2015 | 134 | my_bitmap_map *old_map = dbug_tmp_use_all_columns(tbl, tbl->write_set); | |
| 2016 | |||
| 2017 | 134 | tbl->fts_doc_id_field->store(static_cast<longlong>(doc_id), true); | |
| 2018 | |||
| 2019 | 134 | dbug_tmp_restore_column_map(tbl->write_set, old_map); | |
| 2020 | 134 | } | |
| 2021 | |||
| 2022 | /** Check for a valid value of innobase_commit_concurrency. | ||
| 2023 | @return 0 for valid innodb_commit_concurrency */ | ||
| 2024 | 17 | static int innobase_commit_concurrency_validate( | |
| 2025 | THD *, /*!< in: thread handle */ | ||
| 2026 | SYS_VAR *, /*!< in: pointer to system | ||
| 2027 | variable */ | ||
| 2028 | void *save, /*!< out: immediate result | ||
| 2029 | for update function */ | ||
| 2030 | struct st_mysql_value *value) /*!< in: incoming string */ | ||
| 2031 | { | ||
| 2032 | long long intbuf; | ||
| 2033 | ulong commit_concurrency; | ||
| 2034 | |||
| 2035 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | DBUG_TRACE; |
| 2036 | |||
| 2037 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
17 | if (value->val_int(value, &intbuf)) { |
| 2038 | /* The value is NULL. That is invalid. */ | ||
| 2039 | ✗ | return 1; | |
| 2040 | } | ||
| 2041 | |||
| 2042 | 17 | *reinterpret_cast<ulong *>(save) = commit_concurrency = | |
| 2043 | 17 | static_cast<ulong>(intbuf); | |
| 2044 | |||
| 2045 | /* Allow the value to be updated, as long as it remains zero | ||
| 2046 | or nonzero. */ | ||
| 2047 | 17 | return !(!commit_concurrency == !innobase_commit_concurrency); | |
| 2048 | 17 | } | |
| 2049 | |||
| 2050 | /** Function for constructing an InnoDB table handler instance. | ||
| 2051 | @param[in,out] hton handlerton for InnoDB | ||
| 2052 | @param[in] table MySQL table | ||
| 2053 | @param[in] partitioned Indicates whether table is partitioned | ||
| 2054 | @param[in] mem_root memory context */ | ||
| 2055 | 10196980 | static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, | |
| 2056 | bool partitioned, MEM_ROOT *mem_root) { | ||
| 2057 |
2/2✓ Branch 0 taken 69535 times.
✓ Branch 1 taken 10127445 times.
|
10196980 | if (partitioned) { |
| 2058 |
2/4✓ Branch 0 taken 69535 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69535 times.
✗ Branch 3 not taken.
|
69535 | ha_innopart *file = new (mem_root) ha_innopart(hton, table); |
| 2059 |
3/6✓ Branch 0 taken 69535 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69535 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 69535 times.
|
69535 | if (file && file->init_partitioning(mem_root)) { |
| 2060 | ✗ | destroy(file); | |
| 2061 | ✗ | return (nullptr); | |
| 2062 | } | ||
| 2063 | 69535 | return (file); | |
| 2064 | } | ||
| 2065 | |||
| 2066 |
2/4✓ Branch 0 taken 10127466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10127468 times.
✗ Branch 3 not taken.
|
10127445 | return (new (mem_root) ha_innobase(hton, table)); |
| 2067 | } | ||
| 2068 | |||
| 2069 | /* General functions */ | ||
| 2070 | |||
| 2071 | /** Returns true if the thread is the replication thread on the slave | ||
| 2072 | server. Used in srv_conc_enter_innodb() to determine if the thread | ||
| 2073 | should be allowed to enter InnoDB - the replication thread is treated | ||
| 2074 | differently than other threads. Also used in | ||
| 2075 | srv_conc_force_exit_innodb(). | ||
| 2076 | @return true if thd is the replication thread */ | ||
| 2077 | 232577 | bool thd_is_replication_slave_thread(THD *thd) /*!< in: thread handle */ | |
| 2078 | { | ||
| 2079 |
3/4✓ Branch 0 taken 232580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 539 times.
✓ Branch 3 taken 232041 times.
|
232577 | return thd != nullptr && thd_slave_thread(thd); |
| 2080 | } | ||
| 2081 | |||
| 2082 | /** Gets information on the durability property requested by thread. | ||
| 2083 | Used when writing either a prepare or commit record to the log | ||
| 2084 | buffer. @return the durability property. */ | ||
| 2085 | 7011527 | enum durability_properties thd_requested_durability( | |
| 2086 | const THD *thd) /*!< in: thread handle */ | ||
| 2087 | { | ||
| 2088 | 7011527 | return (thd_get_durability_property(thd)); | |
| 2089 | } | ||
| 2090 | |||
| 2091 | /** Returns true if transaction should be flagged as read-only. | ||
| 2092 | @return true if the thd is marked as read-only */ | ||
| 2093 | 17653923 | bool thd_trx_is_read_only(THD *thd) /*!< in: thread handle */ | |
| 2094 | { | ||
| 2095 |
4/4✓ Branch 0 taken 17458018 times.
✓ Branch 1 taken 195905 times.
✓ Branch 2 taken 12158071 times.
✓ Branch 3 taken 5300244 times.
|
17653923 | return (thd != nullptr && thd_tx_is_read_only(thd)); |
| 2096 | } | ||
| 2097 | |||
| 2098 | /** | ||
| 2099 | Check if the transaction can be rolled back | ||
| 2100 | @param[in] requestor Session requesting the lock | ||
| 2101 | @param[in] holder Session that holds the lock | ||
| 2102 | @return the session that will be rolled back, null don't care */ | ||
| 2103 | |||
| 2104 | 1 | THD *thd_trx_arbitrate(THD *requestor, THD *holder) { | |
| 2105 | /* Non-user (thd==0) transactions by default can't rollback, in | ||
| 2106 | practice DDL transactions should never rollback and that's because | ||
| 2107 | they should never wait on table/record locks either */ | ||
| 2108 | |||
| 2109 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | ut_a(holder != nullptr); |
| 2110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | ut_a(holder != requestor); |
| 2111 | |||
| 2112 | 1 | THD *victim = thd_tx_arbitrate(requestor, holder); | |
| 2113 | |||
| 2114 |
3/8✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
|
1 | ut_a(victim == nullptr || victim == requestor || victim == holder); |
| 2115 | |||
| 2116 | 1 | return (victim); | |
| 2117 | } | ||
| 2118 | |||
| 2119 | /** | ||
| 2120 | @param[in] thd Session to check | ||
| 2121 | @return the priority */ | ||
| 2122 | |||
| 2123 | 357106772 | int thd_trx_priority(THD *thd) { | |
| 2124 |
1/2✓ Branch 0 taken 357107036 times.
✗ Branch 1 not taken.
|
357106772 | return (thd == nullptr ? 0 : thd_tx_priority(thd)); |
| 2125 | } | ||
| 2126 | |||
| 2127 | /** Check if the transaction is an auto-commit transaction. true also | ||
| 2128 | implies that it is a SELECT (read-only) transaction. | ||
| 2129 | @return true if the transaction is an auto commit read-only transaction. */ | ||
| 2130 | 19803689 | bool thd_trx_is_auto_commit(THD *thd) /*!< in: thread handle, can be NULL */ | |
| 2131 | { | ||
| 2132 | 17458677 | return thd != nullptr && | |
| 2133 |
4/4✓ Branch 0 taken 17458785 times.
✓ Branch 1 taken 2344904 times.
✓ Branch 2 taken 16350978 times.
✓ Branch 3 taken 1107699 times.
|
36154704 | !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) && |
| 2134 |
2/2✓ Branch 0 taken 12746471 times.
✓ Branch 1 taken 3604544 times.
|
36154596 | thd_is_query_block(thd); |
| 2135 | } | ||
| 2136 | |||
| 2137 | extern "C" long long thd_start_time(const THD *thd); | ||
| 2138 | |||
| 2139 | 17457925 | std::chrono::system_clock::time_point thd_start_time(THD *) { | |
| 2140 | // FIXME: This function should be added to the server code. | ||
| 2141 | // return(thd_start_time(thd)); | ||
| 2142 | 17457925 | return std::chrono::system_clock::now(); | |
| 2143 | } | ||
| 2144 | |||
| 2145 | /** Enter InnoDB engine after checking the max number of user threads | ||
| 2146 | allowed, else the thread is put into sleep. | ||
| 2147 | @param[in,out] prebuilt row prebuilt handler | ||
| 2148 | @return InnoDB error code. */ | ||
| 2149 | 453762881 | static inline dberr_t innobase_srv_conc_enter_innodb(row_prebuilt_t *prebuilt) { | |
| 2150 | /* We rely on server to do external_lock(F_UNLCK) to reset the | ||
| 2151 | srv_conc.n_active counter. */ | ||
| 2152 |
2/2✓ Branch 0 taken 214641393 times.
✓ Branch 1 taken 239122971 times.
|
453762881 | if (prebuilt->skip_concurrency_ticket()) { |
| 2153 | 214641393 | return DB_SUCCESS; | |
| 2154 | } | ||
| 2155 | |||
| 2156 | 239122971 | dberr_t err = DB_SUCCESS; | |
| 2157 | 239122971 | trx_t *trx = prebuilt->trx; | |
| 2158 | |||
| 2159 |
2/2✓ Branch 0 taken 30100 times.
✓ Branch 1 taken 239092871 times.
|
239122971 | if (srv_thread_concurrency) { |
| 2160 |
2/2✓ Branch 0 taken 28220 times.
✓ Branch 1 taken 1880 times.
|
30100 | if (trx->n_tickets_to_enter_innodb > 0) { |
| 2161 | /* If trx has 'free tickets' to enter the engine left, | ||
| 2162 | then use one such ticket */ | ||
| 2163 | |||
| 2164 | 28220 | --trx->n_tickets_to_enter_innodb; | |
| 2165 | |||
| 2166 |
2/4✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1879 times.
|
3759 | } else if (trx->mysql_thd != nullptr && |
| 2167 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1879 times.
|
1880 | thd_is_replication_slave_thread(trx->mysql_thd)) { |
| 2168 | ✗ | ut::wait_for( | |
| 2169 | ✗ | [&]() { | |
| 2170 | ✗ | return srv_conc_get_active_threads() < | |
| 2171 | ✗ | (int32_t)srv_thread_concurrency; | |
| 2172 | }, | ||
| 2173 | ✗ | get_srv_replication_delay()); | |
| 2174 | |||
| 2175 | } else { | ||
| 2176 | 1879 | err = srv_conc_enter_innodb(prebuilt); | |
| 2177 | } | ||
| 2178 | } | ||
| 2179 | |||
| 2180 | 239122971 | return err; | |
| 2181 | } | ||
| 2182 | |||
| 2183 | /** Note that the thread wants to leave InnoDB only if it doesn't have | ||
| 2184 | any spare tickets. | ||
| 2185 | @param[in,out] prebuilt row prebuilt handler */ | ||
| 2186 | 453764615 | static inline void innobase_srv_conc_exit_innodb(row_prebuilt_t *prebuilt) { | |
| 2187 | /* We rely on server to do external_lock(F_UNLCK) to reset the | ||
| 2188 | srv_conc.n_active counter. */ | ||
| 2189 |
3/4✓ Branch 0 taken 453764889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 214641431 times.
✓ Branch 3 taken 239123458 times.
|
453764615 | if (prebuilt->skip_concurrency_ticket()) { |
| 2190 | 214641431 | return; | |
| 2191 | } | ||
| 2192 | |||
| 2193 | 239123458 | trx_t *trx = prebuilt->trx; | |
| 2194 | #ifdef UNIV_DEBUG | ||
| 2195 | 239123458 | btrsea_sync_check check(trx->has_search_latch); | |
| 2196 | |||
| 2197 |
2/4✓ Branch 0 taken 239123471 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 239123445 times.
|
239123346 | ut_ad(!sync_check_iterate(check)); |
| 2198 | #endif /* UNIV_DEBUG */ | ||
| 2199 | |||
| 2200 | /* This is to avoid making an unnecessary function call. */ | ||
| 2201 |
2/2✓ Branch 0 taken 30098 times.
✓ Branch 1 taken 239093347 times.
|
239123445 | if (trx->declared_to_be_inside_innodb && |
| 2202 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 30095 times.
|
30098 | trx->n_tickets_to_enter_innodb == 0) { |
| 2203 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | srv_conc_force_exit_innodb(trx); |
| 2204 | } | ||
| 2205 | 239123445 | } | |
| 2206 | |||
| 2207 | /** Force a thread to leave InnoDB even if it has spare tickets. */ | ||
| 2208 | 171070329 | static inline void innobase_srv_conc_force_exit_innodb( | |
| 2209 | trx_t *trx) /*!< in: transaction handle */ | ||
| 2210 | { | ||
| 2211 | #ifdef UNIV_DEBUG | ||
| 2212 | 171070329 | btrsea_sync_check check(trx->has_search_latch); | |
| 2213 | |||
| 2214 |
2/4✓ Branch 0 taken 171070605 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 171070558 times.
|
171070505 | ut_ad(!sync_check_iterate(check)); |
| 2215 | #endif /* UNIV_DEBUG */ | ||
| 2216 | |||
| 2217 | /* This is to avoid making an unnecessary function call. */ | ||
| 2218 |
2/2✓ Branch 0 taken 1875 times.
✓ Branch 1 taken 171068683 times.
|
171070558 | if (trx->declared_to_be_inside_innodb) { |
| 2219 |
1/2✓ Branch 0 taken 1875 times.
✗ Branch 1 not taken.
|
1875 | srv_conc_force_exit_innodb(trx); |
| 2220 | } | ||
| 2221 | 171070558 | } | |
| 2222 | |||
| 2223 | /** Returns the NUL terminated value of glob_hostname. | ||
| 2224 | @return pointer to glob_hostname. */ | ||
| 2225 | 703 | const char *server_get_hostname() { return (glob_hostname); } | |
| 2226 | |||
| 2227 | /** Returns true if the transaction this thread is processing has edited | ||
| 2228 | non-transactional tables. Used by the deadlock detector when deciding | ||
| 2229 | which transaction to rollback in case of a deadlock - we try to avoid | ||
| 2230 | rolling back transactions that have edited non-transactional tables. | ||
| 2231 | @return true if non-transactional tables have been edited */ | ||
| 2232 | 376 | bool thd_has_edited_nontrans_tables(THD *thd) /*!< in: thread handle */ | |
| 2233 | { | ||
| 2234 | 376 | return thd_non_transactional_update(thd); | |
| 2235 | } | ||
| 2236 | |||
| 2237 | /** Returns true if the thread is executing a SELECT statement. | ||
| 2238 | @return true if thd is executing SELECT */ | ||
| 2239 | 16612932 | bool thd_is_query_block(const THD *thd) /*!< in: thread handle */ | |
| 2240 | { | ||
| 2241 | 16612932 | return thd_sql_command(thd) == SQLCOM_SELECT; | |
| 2242 | } | ||
| 2243 | |||
| 2244 | /** Checks sys_vars and determines if allocator should mark | ||
| 2245 | large memory segments with MADV_DONTDUMP | ||
| 2246 | @return true iff @@global.core_file AND | ||
| 2247 | NOT @@global.innodb_buffer_pool_in_core_file */ | ||
| 2248 | 11994 | bool innobase_should_madvise_buf_pool() { | |
| 2249 |
4/4✓ Branch 0 taken 11563 times.
✓ Branch 1 taken 431 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 11559 times.
|
11994 | return (test_flags & TEST_CORE_ON_SIGNAL) && !srv_buffer_pool_in_core_file; |
| 2250 | } | ||
| 2251 | |||
| 2252 | /** Make sure that core file will not be generated, as generating a core file | ||
| 2253 | might violate our promise to not dump buffer pool data, and/or might dump not | ||
| 2254 | the expected memory pages due to failure in using madvise */ | ||
| 2255 | ✗ | void innobase_disable_core_dump() { | |
| 2256 | /* TODO: There is a race condition here, as test_flags is not an atomic<> | ||
| 2257 | and there might be multiple threads calling this function | ||
| 2258 | in parallel (once for each buffer pool thread). | ||
| 2259 | One approach would be to use a loop with os_compare_and_swap_ulint | ||
| 2260 | unfortunately test_flags is defined as uint, not ulint, and we don't | ||
| 2261 | have nice portable function for dealing with uint in InnoDB. | ||
| 2262 | Moreover that would only prevent problems with mangled bits, but not | ||
| 2263 | help at all with that some other thread might be reading test_flags | ||
| 2264 | and making decisions based on observed value while we are changing it. | ||
| 2265 | The good news is that all these threads try to do the same thing: clear the | ||
| 2266 | same bit. So this happens to work. | ||
| 2267 | */ | ||
| 2268 | |||
| 2269 | ✗ | test_flags &= ~TEST_CORE_ON_SIGNAL; | |
| 2270 | } | ||
| 2271 | |||
| 2272 | 238918 | std::chrono::seconds thd_lock_wait_timeout(THD *thd) { | |
| 2273 | /* According to <mysql/plugin.h>, passing thd == NULL | ||
| 2274 | returns the global value of the session variable. */ | ||
| 2275 | 238918 | return std::chrono::seconds{THDVAR(thd, lock_wait_timeout)}; | |
| 2276 | } | ||
| 2277 | |||
| 2278 | /** Is FT ignore stopwords variable set. | ||
| 2279 | @param thd Thread object | ||
| 2280 | @return true if ft_ignore_stopwords is set, false otherwise. */ | ||
| 2281 | 17524614 | bool thd_has_ft_ignore_stopwords(THD *thd) noexcept { | |
| 2282 | 17524614 | return (THDVAR(thd, ft_ignore_stopwords)); | |
| 2283 | } | ||
| 2284 | |||
| 2285 | 41613 | void thd_set_lock_wait_time(THD *thd, | |
| 2286 | std::chrono::steady_clock::duration value) { | ||
| 2287 |
1/2✓ Branch 0 taken 41613 times.
✗ Branch 1 not taken.
|
41613 | if (thd) { |
| 2288 |
1/2✓ Branch 0 taken 41613 times.
✗ Branch 1 not taken.
|
41613 | thd_storage_lock_wait( |
| 2289 | thd, | ||
| 2290 | 83226 | std::chrono::duration_cast<std::chrono::microseconds>(value).count()); | |
| 2291 | } | ||
| 2292 | 41613 | } | |
| 2293 | |||
| 2294 | 81815 | const char *thd_innodb_tmpdir(THD *thd) { | |
| 2295 | #ifdef UNIV_DEBUG | ||
| 2296 |
2/2✓ Branch 0 taken 81761 times.
✓ Branch 1 taken 54 times.
|
81815 | if (thd != nullptr) { |
| 2297 |
1/2✓ Branch 0 taken 81761 times.
✗ Branch 1 not taken.
|
81761 | auto trx = thd_to_trx(thd); |
| 2298 | |||
| 2299 | 81761 | btrsea_sync_check check(trx->has_search_latch); | |
| 2300 | |||
| 2301 |
2/4✓ Branch 0 taken 81761 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 81761 times.
|
81761 | ut_ad(!sync_check_iterate(check)); |
| 2302 | 81761 | } | |
| 2303 | #endif /* UNIV_DEBUG */ | ||
| 2304 | |||
| 2305 | 81815 | const char *tmp_dir = THDVAR(thd, tmpdir); | |
| 2306 | |||
| 2307 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 81798 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
81815 | if (tmp_dir != nullptr && *tmp_dir == '\0') { |
| 2308 | ✗ | tmp_dir = nullptr; | |
| 2309 | } | ||
| 2310 | |||
| 2311 | 81815 | return tmp_dir; | |
| 2312 | } | ||
| 2313 | |||
| 2314 | /** Obtain the private handler of InnoDB session specific data. | ||
| 2315 | @param[in,out] thd MySQL thread handler. | ||
| 2316 | @return reference to private handler */ | ||
| 2317 | |||
| 2318 | 3475226278 | [[nodiscard]] innodb_session_t *&thd_to_innodb_session(THD *thd) { | |
| 2319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3475226278 times.
|
3475226278 | assert(innodb_hton_ptr->slot != HA_SLOT_UNDEF); |
| 2320 | |||
| 2321 | innodb_session_t *&innodb_session = | ||
| 2322 | 3475226278 | *(innodb_session_t **)thd_ha_data(thd, innodb_hton_ptr); | |
| 2323 | |||
| 2324 |
2/2✓ Branch 0 taken 3457212037 times.
✓ Branch 1 taken 18021504 times.
|
3475233541 | if (innodb_session != nullptr) { |
| 2325 | 3457212037 | return (innodb_session); | |
| 2326 | } | ||
| 2327 | |||
| 2328 | 18021504 | innodb_session = ut::new_withkey<innodb_session_t>(UT_NEW_THIS_FILE_PSI_KEY); | |
| 2329 | 18022887 | return (innodb_session); | |
| 2330 | } | ||
| 2331 | |||
| 2332 | /** Obtain the InnoDB transaction of a MySQL thread. | ||
| 2333 | @param[in,out] thd MySQL thread handler. | ||
| 2334 | @return reference to transaction pointer */ | ||
| 2335 | |||
| 2336 | 3360873537 | [[nodiscard]] trx_t *&thd_to_trx(THD *thd) { | |
| 2337 | 3360873537 | innodb_session_t *&innodb_session = thd_to_innodb_session(thd); | |
| 2338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3360878926 times.
|
3360882940 | ut_ad(innodb_session != nullptr); |
| 2339 | |||
| 2340 | 3360878926 | return (innodb_session->m_trx); | |
| 2341 | } | ||
| 2342 | |||
| 2343 | 76062 | ulong thd_parallel_read_threads(THD *thd) { | |
| 2344 | 76062 | return THDVAR(thd, parallel_read_threads); | |
| 2345 | } | ||
| 2346 | |||
| 2347 | 35474 | ulong thd_ddl_buffer_size(THD *thd) { return THDVAR(thd, ddl_buffer_size); } | |
| 2348 | |||
| 2349 | 35474 | size_t thd_ddl_threads(THD *thd) noexcept { return THDVAR(thd, ddl_threads); } | |
| 2350 | |||
| 2351 | /** Check if statement is of type INSERT .... SELECT that involves | ||
| 2352 | use of intrinsic tables. | ||
| 2353 | @param[in] user_thd thread handler | ||
| 2354 | @return true if INSERT .... SELECT statement. */ | ||
| 2355 | 71154200 | static inline bool thd_is_ins_sel_stmt(THD *user_thd) { | |
| 2356 | /* If the session involves use of intrinsic table | ||
| 2357 | and it is trying to fetch the result from non-temporary tables | ||
| 2358 | it indicates "insert .... select" statement. For non-temporary | ||
| 2359 | table this is verifed using the locked tables count but for | ||
| 2360 | intrinsic table as external_lock is not invoked this count is | ||
| 2361 | not updated. | ||
| 2362 | |||
| 2363 | Why is this needed ? | ||
| 2364 | Use of AHI is blocked if statement is insert .... select statement. */ | ||
| 2365 | 71154200 | innodb_session_t *innodb_priv = thd_to_innodb_session(user_thd); | |
| 2366 | 71154450 | return (innodb_priv->count_register_table_handler() > 0 ? true : false); | |
| 2367 | } | ||
| 2368 | |||
| 2369 | /** Add the table handler to thread cache. | ||
| 2370 | Obtain the InnoDB transaction of a MySQL thread. | ||
| 2371 | @param[in,out] table table handler | ||
| 2372 | @param[in,out] heap heap for allocating system columns. | ||
| 2373 | @param[in,out] thd MySQL thread handler */ | ||
| 2374 | 182644 | static inline void add_table_to_thread_cache(dict_table_t *table, | |
| 2375 | mem_heap_t *heap, THD *thd) { | ||
| 2376 | 182644 | dict_table_add_system_columns(table, heap); | |
| 2377 | |||
| 2378 | 182644 | dict_table_set_big_rows(table); | |
| 2379 | |||
| 2380 | 182644 | innodb_session_t *&priv = thd_to_innodb_session(thd); | |
| 2381 | 182644 | priv->register_table_handler(table->name.m_name, table); | |
| 2382 | 182644 | } | |
| 2383 | |||
| 2384 | /** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth | ||
| 2385 | time calls srv_active_wake_master_thread. This function should be used | ||
| 2386 | when a single database operation may introduce a small need for | ||
| 2387 | server utility activity, like checkpointing. */ | ||
| 2388 | 65525682 | inline void innobase_active_small(void) { | |
| 2389 | 65525682 | innobase_active_counter++; | |
| 2390 | |||
| 2391 |
2/2✓ Branch 0 taken 2041740 times.
✓ Branch 1 taken 63483942 times.
|
65525682 | if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) { |
| 2392 | 2041740 | srv_active_wake_master_thread(); | |
| 2393 | } | ||
| 2394 | 65525682 | } | |
| 2395 | |||
| 2396 | /** Converts an InnoDB error code to a MySQL error code. | ||
| 2397 | Also tells to MySQL about a possible transaction rollback inside InnoDB caused | ||
| 2398 | by a lock wait timeout or a deadlock. | ||
| 2399 | @param[in] error InnoDB error code. | ||
| 2400 | @param[in] flags InnoDB table flags or 0. | ||
| 2401 | @param[in] thd MySQL thread or NULL. | ||
| 2402 | @return MySQL error code */ | ||
| 2403 | 90370017 | int convert_error_code_to_mysql(dberr_t error, uint32_t flags, THD *thd) { | |
| 2404 |
32/48✓ Branch 0 taken 89728294 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 255 times.
✓ Branch 5 taken 639911 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 493 times.
✓ Branch 11 taken 404 times.
✓ Branch 12 taken 87 times.
✓ Branch 13 taken 85 times.
✓ Branch 14 taken 10 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 22 times.
✓ Branch 17 taken 8 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 26 times.
✓ Branch 24 taken 34 times.
✓ Branch 25 taken 11 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✓ Branch 29 taken 6 times.
✓ Branch 30 taken 10 times.
✓ Branch 31 taken 213 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 15 times.
✓ Branch 34 taken 10 times.
✓ Branch 35 taken 8 times.
✓ Branch 36 taken 26 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 1 times.
✓ Branch 43 taken 55 times.
✓ Branch 44 taken 3 times.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
|
90370017 | switch (error) { |
| 2405 | 89728294 | case DB_SUCCESS: | |
| 2406 | 89728294 | return (0); | |
| 2407 | |||
| 2408 | 39 | case DB_INTERRUPTED: | |
| 2409 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 38 times.
|
39 | thd_set_kill_status(thd != nullptr ? thd : current_thd); |
| 2410 | 38 | return (HA_ERR_GENERIC); | |
| 2411 | |||
| 2412 | 1 | case DB_FOREIGN_EXCEED_MAX_CASCADE: | |
| 2413 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | ut_ad(thd); |
| 2414 | 1 | my_error(ER_FK_DEPTH_EXCEEDED, MYF(0), FK_MAX_CASCADE_DEL); | |
| 2415 | 1 | return (HA_ERR_FK_DEPTH_EXCEEDED); | |
| 2416 | |||
| 2417 | ✗ | case DB_CANT_CREATE_GEOMETRY_OBJECT: | |
| 2418 | ✗ | my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0)); | |
| 2419 | ✗ | return (HA_ERR_NULL_IN_SPATIAL); | |
| 2420 | |||
| 2421 | 255 | case DB_ERROR: | |
| 2422 | default: | ||
| 2423 | 255 | return (HA_ERR_GENERIC); /* unspecified error */ | |
| 2424 | |||
| 2425 | 639911 | case DB_DUPLICATE_KEY: | |
| 2426 | /* Be cautious with returning this error, since | ||
| 2427 | mysql could re-enter the storage layer to get | ||
| 2428 | duplicated key info, the operation requires a | ||
| 2429 | valid table handle and/or transaction information, | ||
| 2430 | which might not always be available in the error | ||
| 2431 | handling stage. */ | ||
| 2432 | 639911 | return (HA_ERR_FOUND_DUPP_KEY); | |
| 2433 | |||
| 2434 | 4 | case DB_READ_ONLY: | |
| 2435 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (srv_force_recovery) { |
| 2436 | 4 | return (HA_ERR_INNODB_FORCED_RECOVERY); | |
| 2437 | } | ||
| 2438 | ✗ | return (HA_ERR_TABLE_READONLY); | |
| 2439 | |||
| 2440 | 3 | case DB_FOREIGN_DUPLICATE_KEY: | |
| 2441 | 3 | return (HA_ERR_FOREIGN_DUPLICATE_KEY); | |
| 2442 | |||
| 2443 | ✗ | case DB_MISSING_HISTORY: | |
| 2444 | ✗ | return (HA_ERR_TABLE_DEF_CHANGED); | |
| 2445 | |||
| 2446 | ✗ | case DB_RECORD_NOT_FOUND: | |
| 2447 | ✗ | return (HA_ERR_NO_ACTIVE_RECORD); | |
| 2448 | |||
| 2449 | 493 | case DB_FORCED_ABORT: | |
| 2450 | case DB_DEADLOCK: | ||
| 2451 | /* Since we rolled back the whole transaction, we must | ||
| 2452 | tell it also to MySQL so that MySQL knows to empty the | ||
| 2453 | cached binlog for this transaction */ | ||
| 2454 | |||
| 2455 |
1/2✓ Branch 0 taken 493 times.
✗ Branch 1 not taken.
|
493 | if (thd != nullptr) { |
| 2456 | 493 | thd_mark_transaction_to_rollback(thd, 1); | |
| 2457 | } | ||
| 2458 | |||
| 2459 | 493 | return (HA_ERR_LOCK_DEADLOCK); | |
| 2460 | |||
| 2461 | 404 | case DB_LOCK_WAIT_TIMEOUT: | |
| 2462 | /* Starting from 5.0.13, we let MySQL just roll back the | ||
| 2463 | latest SQL statement in a lock wait timeout. Previously, we | ||
| 2464 | rolled back the whole transaction. */ | ||
| 2465 | |||
| 2466 |
1/2✓ Branch 0 taken 404 times.
✗ Branch 1 not taken.
|
404 | if (thd) { |
| 2467 | 404 | thd_mark_transaction_to_rollback(thd, (int)row_rollback_on_timeout); | |
| 2468 | } | ||
| 2469 | |||
| 2470 | 405 | return (HA_ERR_LOCK_WAIT_TIMEOUT); | |
| 2471 | |||
| 2472 | 87 | case DB_NO_REFERENCED_ROW: | |
| 2473 | 87 | return (HA_ERR_NO_REFERENCED_ROW); | |
| 2474 | |||
| 2475 | 85 | case DB_ROW_IS_REFERENCED: | |
| 2476 | 85 | return (HA_ERR_ROW_IS_REFERENCED); | |
| 2477 | |||
| 2478 | 10 | case DB_NO_FK_ON_S_BASE_COL: | |
| 2479 | case DB_CANNOT_ADD_CONSTRAINT: | ||
| 2480 | case DB_CHILD_NO_INDEX: | ||
| 2481 | case DB_PARENT_NO_INDEX: | ||
| 2482 | 10 | return (HA_ERR_CANNOT_ADD_FOREIGN); | |
| 2483 | |||
| 2484 | 3 | case DB_CANNOT_DROP_CONSTRAINT: | |
| 2485 | |||
| 2486 | 3 | return (HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit | |
| 2487 | misleading, a new MySQL error | ||
| 2488 | code should be introduced */ | ||
| 2489 | |||
| 2490 | 22 | case DB_CORRUPTION: | |
| 2491 | 22 | return (HA_ERR_CRASHED); | |
| 2492 | |||
| 2493 | 8 | case DB_OUT_OF_FILE_SPACE: | |
| 2494 | 8 | return (HA_ERR_RECORD_FILE_FULL); | |
| 2495 | |||
| 2496 | ✗ | case DB_OUT_OF_DISK_SPACE: | |
| 2497 | ✗ | return (HA_ERR_DISK_FULL_NOWAIT); | |
| 2498 | |||
| 2499 | ✗ | case DB_TEMP_FILE_WRITE_FAIL: | |
| 2500 | ✗ | return (HA_ERR_TEMP_FILE_WRITE_FAILURE); | |
| 2501 | |||
| 2502 | ✗ | case DB_TABLE_IN_FK_CHECK: | |
| 2503 | ✗ | return (HA_ERR_TABLE_IN_FK_CHECK); | |
| 2504 | |||
| 2505 | ✗ | case DB_TABLE_IS_BEING_USED: | |
| 2506 | ✗ | return (HA_ERR_WRONG_COMMAND); | |
| 2507 | |||
| 2508 | 2 | case DB_TABLE_NOT_FOUND: | |
| 2509 | 2 | return (HA_ERR_NO_SUCH_TABLE); | |
| 2510 | |||
| 2511 | 26 | case DB_TABLESPACE_NOT_FOUND: | |
| 2512 | 26 | return (HA_ERR_TABLESPACE_MISSING); | |
| 2513 | |||
| 2514 | 34 | case DB_TOO_BIG_RECORD: { | |
| 2515 | /* If prefix is true then a 768-byte prefix is stored | ||
| 2516 | locally for BLOB fields. Refer to dict_table_get_format(). | ||
| 2517 | We limit max record size to 16k for 64k page size. */ | ||
| 2518 | 34 | bool prefix = !DICT_TF_HAS_ATOMIC_BLOBS(flags); | |
| 2519 |
4/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 17 times.
|
68 | my_printf_error( |
| 2520 | ER_TOO_BIG_ROWSIZE, | ||
| 2521 | "Row size too large (> %lu). Changing some columns" | ||
| 2522 | " to TEXT or BLOB %smay help. In current row" | ||
| 2523 | " format, BLOB prefix of %d bytes is stored inline.", | ||
| 2524 | MYF(0), | ||
| 2525 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | srv_page_size == UNIV_PAGE_SIZE_MAX |
| 2526 | ? REC_MAX_DATA_SIZE - 1 | ||
| 2527 | 34 | : page_get_free_space_of_empty(flags & DICT_TF_COMPACT) / 2, | |
| 2528 | prefix ? "or using ROW_FORMAT=DYNAMIC or" | ||
| 2529 | " ROW_FORMAT=COMPRESSED " | ||
| 2530 | : "", | ||
| 2531 | prefix ? DICT_MAX_FIXED_COL_LEN : 0); | ||
| 2532 | 34 | return (HA_ERR_TOO_BIG_ROW); | |
| 2533 | } | ||
| 2534 | |||
| 2535 | 11 | case DB_TOO_BIG_INDEX_COL: | |
| 2536 | 11 | my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0), | |
| 2537 | DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags)); | ||
| 2538 | 11 | return (HA_ERR_INDEX_COL_TOO_LONG); | |
| 2539 | |||
| 2540 | ✗ | case DB_NO_SAVEPOINT: | |
| 2541 | ✗ | return (HA_ERR_NO_SAVEPOINT); | |
| 2542 | |||
| 2543 | ✗ | case DB_LOCK_TABLE_FULL: | |
| 2544 | /* Since we rolled back the whole transaction, we must | ||
| 2545 | tell it also to MySQL so that MySQL knows to empty the | ||
| 2546 | cached binlog for this transaction */ | ||
| 2547 | |||
| 2548 | ✗ | if (thd) { | |
| 2549 | ✗ | thd_mark_transaction_to_rollback(thd, 1); | |
| 2550 | } | ||
| 2551 | |||
| 2552 | ✗ | return (HA_ERR_LOCK_TABLE_FULL); | |
| 2553 | |||
| 2554 | 3 | case DB_FTS_INVALID_DOCID: | |
| 2555 | 3 | return (HA_FTS_INVALID_DOCID); | |
| 2556 | 6 | case DB_FTS_EXCEED_RESULT_CACHE_LIMIT: | |
| 2557 | 6 | return (HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT); | |
| 2558 | 10 | case DB_TOO_MANY_CONCURRENT_TRXS: | |
| 2559 | 10 | return (HA_ERR_TOO_MANY_CONCURRENT_TRXS); | |
| 2560 | 213 | case DB_UNSUPPORTED: | |
| 2561 | 213 | return (HA_ERR_UNSUPPORTED); | |
| 2562 | ✗ | case DB_INDEX_CORRUPT: | |
| 2563 | ✗ | return (HA_ERR_INDEX_CORRUPT); | |
| 2564 | 15 | case DB_UNDO_RECORD_TOO_BIG: | |
| 2565 | 15 | return (HA_ERR_UNDO_REC_TOO_BIG); | |
| 2566 | 10 | case DB_OUT_OF_MEMORY: | |
| 2567 | 10 | return (HA_ERR_OUT_OF_MEM); | |
| 2568 | 8 | case DB_TABLESPACE_EXISTS: | |
| 2569 | 8 | return (HA_ERR_TABLESPACE_EXISTS); | |
| 2570 | 26 | case DB_TABLESPACE_DELETED: | |
| 2571 | 26 | return (HA_ERR_TABLESPACE_MISSING); | |
| 2572 | ✗ | case DB_IDENTIFIER_TOO_LONG: | |
| 2573 | ✗ | return (HA_ERR_INTERNAL_ERROR); | |
| 2574 | ✗ | case DB_TOO_LONG_PATH: | |
| 2575 | ✗ | return (HA_ERR_TOO_LONG_PATH); | |
| 2576 | 1 | case DB_TABLE_CORRUPT: | |
| 2577 | 1 | return (HA_ERR_TABLE_CORRUPT); | |
| 2578 | ✗ | case DB_FTS_TOO_MANY_WORDS_IN_PHRASE: | |
| 2579 | ✗ | return (HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE); | |
| 2580 | ✗ | case DB_WRONG_FILE_NAME: | |
| 2581 | ✗ | return (HA_ERR_WRONG_FILE_NAME); | |
| 2582 | 1 | case DB_COMPUTE_VALUE_FAILED: | |
| 2583 | 1 | return (HA_ERR_COMPUTE_FAILED); | |
| 2584 | 55 | case DB_LOCK_NOWAIT: | |
| 2585 | 55 | my_error(ER_LOCK_NOWAIT, MYF(0)); | |
| 2586 | 55 | return (HA_ERR_NO_WAIT_LOCK); | |
| 2587 | 3 | case DB_NO_SESSION_TEMP: | |
| 2588 | 3 | return (HA_ERR_NO_SESSION_TEMP); | |
| 2589 | 1 | case DB_BTREE_LEVEL_LIMIT_EXCEEDED: | |
| 2590 | 1 | return (HA_ERR_INTERNAL_ERROR); | |
| 2591 | ✗ | case DB_FTS_TOO_MANY_NESTED_EXP: | |
| 2592 | ✗ | return (HA_ERR_FTS_TOO_MANY_NESTED_EXP); | |
| 2593 | ✗ | case DB_IO_NO_PUNCH_HOLE: | |
| 2594 | case DB_IO_NO_PUNCH_HOLE_FS: | ||
| 2595 | case DB_IO_NO_PUNCH_HOLE_TABLESPACE: | ||
| 2596 | ✗ | return HA_ERR_UNSUPPORTED; | |
| 2597 | } | ||
| 2598 | } | ||
| 2599 | |||
| 2600 | /** Prints info of a THD object (== user session thread) to the given file. */ | ||
| 2601 | 572 | void innobase_mysql_print_thd( | |
| 2602 | FILE *f, /*!< in: output stream */ | ||
| 2603 | THD *thd, /*!< in: MySQL THD object */ | ||
| 2604 | uint max_query_len) /*!< in: max query length to print, or 0 to | ||
| 2605 | use the default max length */ | ||
| 2606 | { | ||
| 2607 | char buffer[1024]; | ||
| 2608 | |||
| 2609 |
2/4✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 572 times.
✗ Branch 3 not taken.
|
572 | fputs(thd_security_context(thd, buffer, sizeof buffer, max_query_len), f); |
| 2610 |
1/2✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
|
572 | putc('\n', f); |
| 2611 | 572 | } | |
| 2612 | |||
| 2613 | /** Get the error message format string. | ||
| 2614 | @return the format string or 0 if not found. */ | ||
| 2615 | 8336 | const char *innobase_get_err_msg(int error_code) /*!< in: MySQL error code */ | |
| 2616 | { | ||
| 2617 | 8336 | return (my_get_err_msg(error_code)); | |
| 2618 | } | ||
| 2619 | |||
| 2620 | /** Get the variable length bounds of the given character set. | ||
| 2621 | @param[in] cset Mysql charset-collation code | ||
| 2622 | @param[out] mbminlen Minimum length of a char (in bytes) | ||
| 2623 | @param[out] mbmaxlen Maximum length of a char (in bytes) */ | ||
| 2624 | 66664007 | void innobase_get_cset_width(ulint cset, ulint *mbminlen, ulint *mbmaxlen) { | |
| 2625 | CHARSET_INFO *cs; | ||
| 2626 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66657236 times.
|
66664007 | ut_ad(cset <= MAX_CHAR_COLL_NUM); |
| 2627 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66644561 times.
|
66657236 | ut_ad(mbminlen); |
| 2628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66641533 times.
|
66644561 | ut_ad(mbmaxlen); |
| 2629 | |||
| 2630 | 66641533 | cs = all_charsets[cset]; | |
| 2631 |
2/2✓ Branch 0 taken 16452410 times.
✓ Branch 1 taken 50189123 times.
|
66641533 | if (cs) { |
| 2632 | 16452410 | *mbminlen = cs->mbminlen; | |
| 2633 | 16452410 | *mbmaxlen = cs->mbmaxlen; | |
| 2634 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16452408 times.
|
16452410 | ut_ad(*mbminlen < DATA_MBMAX); |
| 2635 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16452417 times.
|
16452408 | ut_ad(*mbmaxlen < DATA_MBMAX); |
| 2636 | } else { | ||
| 2637 | 50189123 | THD *thd = current_thd; | |
| 2638 | |||
| 2639 |
6/6✓ Branch 0 taken 44204909 times.
✓ Branch 1 taken 5984985 times.
✓ Branch 2 taken 417512 times.
✓ Branch 3 taken 43787515 times.
✓ Branch 4 taken 417512 times.
✓ Branch 5 taken 49772500 times.
|
50189894 | if (thd && thd_sql_command(thd) == SQLCOM_DROP_TABLE) { |
| 2640 | /* Fix bug#46256: allow tables to be dropped if the | ||
| 2641 | collation is not found, but issue a warning. */ | ||
| 2642 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 417512 times.
|
417512 | if (cset != 0) { |
| 2643 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNKNOWN_COLLATION); | |
| 2644 | } | ||
| 2645 | } else { | ||
| 2646 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49766888 times.
|
49772500 | ut_a(cset == 0); |
| 2647 | } | ||
| 2648 | |||
| 2649 | 50192922 | *mbminlen = *mbmaxlen = 0; | |
| 2650 | } | ||
| 2651 | 66645339 | } | |
| 2652 | |||
| 2653 | /********************************************************************** | ||
| 2654 | Check if the length of the identifier exceeds the maximum allowed. | ||
| 2655 | return true when length of identifier is too long. */ | ||
| 2656 | 358 | bool innobase_check_identifier_length( | |
| 2657 | const char *id) /* in: FK identifier to check excluding the | ||
| 2658 | database portion. */ | ||
| 2659 | { | ||
| 2660 | 358 | int well_formed_error = 0; | |
| 2661 | 358 | CHARSET_INFO *cs = system_charset_info; | |
| 2662 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | DBUG_TRACE; |
| 2663 | |||
| 2664 |
1/2✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
|
358 | size_t len = cs->cset->well_formed_len(cs, id, id + strlen(id), NAME_CHAR_LEN, |
| 2665 | &well_formed_error); | ||
| 2666 | |||
| 2667 |
2/4✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
|
358 | if (well_formed_error || len != strlen(id)) { |
| 2668 | ✗ | my_error(ER_TOO_LONG_IDENT, MYF(0), id); | |
| 2669 | ✗ | return true; | |
| 2670 | } | ||
| 2671 | 358 | return false; | |
| 2672 | 358 | } | |
| 2673 | #endif /* !UNIV_HOTBACKUP */ | ||
| 2674 | |||
| 2675 | /** Compares NUL-terminated UTF-8 strings case insensitively. | ||
| 2676 | @return 0 if a=b, <0 if a\<b, >1 if a>b */ | ||
| 2677 | 35786178 | int innobase_strcasecmp(const char *a, /*!< in: first string to compare */ | |
| 2678 | const char *b) /*!< in: second string to compare */ | ||
| 2679 | { | ||
| 2680 |
2/2✓ Branch 0 taken 1162202 times.
✓ Branch 1 taken 34623976 times.
|
35786178 | if (!a) { |
| 2681 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1162202 times.
|
1162202 | if (!b) { |
| 2682 | ✗ | return (0); | |
| 2683 | } else { | ||
| 2684 | 1162202 | return (-1); | |
| 2685 | } | ||
| 2686 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34623976 times.
|
34623976 | } else if (!b) { |
| 2687 | ✗ | return (1); | |
| 2688 | } | ||
| 2689 | |||
| 2690 | 34623976 | return (my_strcasecmp(system_charset_info, a, b)); | |
| 2691 | } | ||
| 2692 | |||
| 2693 | #ifndef UNIV_HOTBACKUP | ||
| 2694 | /** Compares NUL-terminated UTF-8 strings case insensitively. The | ||
| 2695 | second string contains wildcards. | ||
| 2696 | @return 0 if a match is found, 1 if not */ | ||
| 2697 | 23959 | static int innobase_wildcasecmp( | |
| 2698 | const char *a, /*!< in: string to compare */ | ||
| 2699 | const char *b) /*!< in: wildcard string to compare */ | ||
| 2700 | { | ||
| 2701 | 23959 | return (wild_case_compare(system_charset_info, a, b)); | |
| 2702 | } | ||
| 2703 | #endif /* !UNIV_HOTBACKUP */ | ||
| 2704 | |||
| 2705 | /** Strip dir name from a full path name and return only the file name | ||
| 2706 | @param[in] path_name full path name | ||
| 2707 | @return file name or "null" if no file name */ | ||
| 2708 | 204 | const char *innobase_basename(const char *path_name) { | |
| 2709 | 204 | const char *name = base_name(path_name); | |
| 2710 | |||
| 2711 |
1/2✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
|
204 | return ((name) ? name : "null"); |
| 2712 | } | ||
| 2713 | |||
| 2714 | #ifndef UNIV_HOTBACKUP | ||
| 2715 | |||
| 2716 | /** Makes all characters in a NUL-terminated UTF-8 string lower case. */ | ||
| 2717 | 942673 | void innobase_casedn_str(char *a) /*!< in/out: string to put in lower case */ | |
| 2718 | { | ||
| 2719 | 942673 | my_casedn_str(system_charset_info, a); | |
| 2720 | 942672 | } | |
| 2721 | |||
| 2722 | /** Makes all characters in a NUL-terminated UTF-8 path string lower case. */ | ||
| 2723 | 30 | void innobase_casedn_path(char *a) /*!< in/out: string to put in lower case */ | |
| 2724 | { | ||
| 2725 | 30 | my_casedn_str(&my_charset_filename, a); | |
| 2726 | 30 | } | |
| 2727 | |||
| 2728 | /** Determines the connection character set. | ||
| 2729 | @return connection character set */ | ||
| 2730 | 61 | const CHARSET_INFO *innobase_get_charset( | |
| 2731 | THD *mysql_thd) /*!< in: MySQL thread handle */ | ||
| 2732 | { | ||
| 2733 | 61 | return (thd_charset(mysql_thd)); | |
| 2734 | } | ||
| 2735 | |||
| 2736 | /** Determines the current SQL statement. | ||
| 2737 | Thread unsafe, can only be called from the thread owning the THD. | ||
| 2738 | @param[in] thd MySQL thread handle | ||
| 2739 | @param[out] length Length of the SQL statement | ||
| 2740 | @return SQL statement string */ | ||
| 2741 | 429023 | const char *innobase_get_stmt_unsafe(THD *thd, size_t *length) { | |
| 2742 | LEX_CSTRING stmt; | ||
| 2743 | |||
| 2744 |
1/2✓ Branch 0 taken 429023 times.
✗ Branch 1 not taken.
|
429023 | stmt = thd_query_unsafe(thd); |
| 2745 | 429023 | *length = stmt.length; | |
| 2746 | 429023 | return (stmt.str); | |
| 2747 | } | ||
| 2748 | |||
| 2749 | /** Determines the current SQL statement. | ||
| 2750 | Thread safe, can be called from any thread as the string is copied | ||
| 2751 | into the provided buffer. | ||
| 2752 | @param[in] thd MySQL thread handle | ||
| 2753 | @param[out] buf Buffer containing SQL statement | ||
| 2754 | @param[in] buflen Length of provided buffer | ||
| 2755 | @return Length of the SQL statement */ | ||
| 2756 | 80 | size_t innobase_get_stmt_safe(THD *thd, char *buf, size_t buflen) { | |
| 2757 | 80 | return (thd_query_safe(thd, buf, buflen)); | |
| 2758 | } | ||
| 2759 | |||
| 2760 | /** Get the current setting of the table_def_size global parameter. We do | ||
| 2761 | a dirty read because for one there is no synchronization object and | ||
| 2762 | secondly there is little harm in doing so even if we get a torn read. | ||
| 2763 | @return value of table_def_size */ | ||
| 2764 | 552518 | ulint innobase_get_table_cache_size(void) { return (table_def_size); } | |
| 2765 | |||
| 2766 | /** Get the current setting of the lower_case_table_names global parameter from | ||
| 2767 | mysqld.cc. We do a dirty read because for one there is no synchronization | ||
| 2768 | object and secondly there is little harm in doing so even if we get a torn | ||
| 2769 | read. | ||
| 2770 | @return value of lower_case_table_names */ | ||
| 2771 | 27619861 | ulint innobase_get_lower_case_table_names(void) { | |
| 2772 | 27619861 | return (lower_case_table_names); | |
| 2773 | } | ||
| 2774 | |||
| 2775 | 18146 | char *innobase_mysql_tmpdir() { return (mysql_tmpdir); } | |
| 2776 | |||
| 2777 | 77832 | os_fd_t innobase_mysql_tmpfile(const char *path) { | |
| 2778 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77833 times.
|
77832 | DBUG_EXECUTE_IF("innobase_tmpfile_creation_failure", return (-1);); |
| 2779 | |||
| 2780 | auto fd = | ||
| 2781 |
2/2✓ Branch 0 taken 11946 times.
✓ Branch 1 taken 65887 times.
|
77833 | (path == nullptr) ? mysql_tmpfile("ib") : mysql_tmpfile_path(path, "ib"); |
| 2782 | |||
| 2783 | 77833 | os_fd_t fd2{OS_FD_CLOSED}; | |
| 2784 | |||
| 2785 |
2/2✓ Branch 0 taken 77832 times.
✓ Branch 1 taken 1 times.
|
77833 | if (fd >= 0) { |
| 2786 | /* Copy the file descriptor, so that the additional resources | ||
| 2787 | allocated by create_temp_file() can be freed by invoking | ||
| 2788 | my_close(). | ||
| 2789 | |||
| 2790 | Because the file descriptor returned by this function | ||
| 2791 | will be passed to fdopen(), it will be closed by invoking | ||
| 2792 | fclose(), which in turn will invoke close() instead of | ||
| 2793 | my_close(). */ | ||
| 2794 | |||
| 2795 | #ifdef _WIN32 | ||
| 2796 | /* Note that on Windows, the integer returned by mysql_tmpfile | ||
| 2797 | has no relation to C runtime file descriptor. Here, we need | ||
| 2798 | to call my_get_osfhandle to get the HANDLE and then convert it | ||
| 2799 | to C runtime filedescriptor. */ | ||
| 2800 | { | ||
| 2801 | HANDLE hDup; | ||
| 2802 | |||
| 2803 | auto hFile = my_get_osfhandle(fd); | ||
| 2804 | |||
| 2805 | auto bOK = | ||
| 2806 | DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(), | ||
| 2807 | &hDup, 0, false, DUPLICATE_SAME_ACCESS); | ||
| 2808 | if (bOK) { | ||
| 2809 | fd2 = _open_osfhandle((intptr_t)hDup, 0); | ||
| 2810 | } else { | ||
| 2811 | my_osmaperr(GetLastError()); | ||
| 2812 | fd2 = OS_FD_CLOSED; | ||
| 2813 | } | ||
| 2814 | } | ||
| 2815 | #else | ||
| 2816 | 77832 | fd2 = dup(fd); | |
| 2817 | #endif | ||
| 2818 | |||
| 2819 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77832 times.
|
77832 | if (fd2 < 0) { |
| 2820 | char errbuf[MYSYS_STRERROR_SIZE]; | ||
| 2821 | |||
| 2822 | ✗ | DBUG_PRINT("error", ("Got error %d on dup", fd2)); | |
| 2823 | |||
| 2824 | ✗ | set_my_errno(errno); | |
| 2825 | |||
| 2826 | ✗ | my_error(EE_OUT_OF_FILERESOURCES, MYF(0), "ib*", my_errno(), | |
| 2827 | my_strerror(errbuf, sizeof(errbuf), my_errno())); | ||
| 2828 | } | ||
| 2829 | |||
| 2830 | 77832 | my_close(fd, MYF(MY_WME)); | |
| 2831 | } | ||
| 2832 | |||
| 2833 | 77832 | return fd2; | |
| 2834 | } | ||
| 2835 | |||
| 2836 | /** Wrapper around MySQL's copy_and_convert function. | ||
| 2837 | @return number of bytes copied to 'to' */ | ||
| 2838 | 272 | static ulint innobase_convert_string( | |
| 2839 | void *to, /*!< out: converted string */ | ||
| 2840 | ulint to_length, /*!< in: number of bytes reserved | ||
| 2841 | for the converted string */ | ||
| 2842 | CHARSET_INFO *to_cs, /*!< in: character set to convert to */ | ||
| 2843 | const void *from, /*!< in: string to convert */ | ||
| 2844 | ulint from_length, /*!< in: number of bytes to convert */ | ||
| 2845 | CHARSET_INFO *from_cs, /*!< in: character set to convert | ||
| 2846 | from */ | ||
| 2847 | uint *errors) /*!< out: number of errors encountered | ||
| 2848 | during the conversion */ | ||
| 2849 | { | ||
| 2850 | 272 | return (copy_and_convert((char *)to, (uint32)to_length, to_cs, | |
| 2851 | (const char *)from, (uint32)from_length, from_cs, | ||
| 2852 | 272 | errors)); | |
| 2853 | } | ||
| 2854 | |||
| 2855 | /** Formats the raw data in "data" (in InnoDB on-disk format) that is of | ||
| 2856 | type DATA_(CHAR|VARCHAR|MYSQL|VARMYSQL) using "charset_coll" and writes | ||
| 2857 | the result to "buf". The result is converted to "system_charset_info". | ||
| 2858 | Not more than "buf_size" bytes are written to "buf". | ||
| 2859 | The result is always NUL-terminated (provided buf_size > 0) and the | ||
| 2860 | number of bytes that were written to "buf" is returned (including the | ||
| 2861 | terminating NUL). | ||
| 2862 | @return number of bytes that were written */ | ||
| 2863 | 272 | ulint innobase_raw_format(const char *data, /*!< in: raw data */ | |
| 2864 | ulint data_len, /*!< in: raw data length | ||
| 2865 | in bytes */ | ||
| 2866 | ulint charset_coll, /*!< in: charset collation */ | ||
| 2867 | char *buf, /*!< out: output buffer */ | ||
| 2868 | ulint buf_size) /*!< in: output buffer size | ||
| 2869 | in bytes */ | ||
| 2870 | { | ||
| 2871 | /* XXX we use a hard limit instead of allocating | ||
| 2872 | but_size bytes from the heap */ | ||
| 2873 | CHARSET_INFO *data_cs; | ||
| 2874 | char buf_tmp[8192]; | ||
| 2875 | ulint buf_tmp_used; | ||
| 2876 | uint num_errors; | ||
| 2877 | |||
| 2878 | 272 | data_cs = all_charsets[charset_coll]; | |
| 2879 | |||
| 2880 | buf_tmp_used = | ||
| 2881 |
1/2✓ Branch 0 taken 272 times.
✗ Branch 1 not taken.
|
272 | innobase_convert_string(buf_tmp, sizeof(buf_tmp), system_charset_info, |
| 2882 | data, data_len, data_cs, &num_errors); | ||
| 2883 | |||
| 2884 | 544 | return (ut_str_sql_format(buf_tmp, buf_tmp_used, buf, buf_size)); | |
| 2885 | } | ||
| 2886 | |||
| 2887 | #endif /* !UNIV_HOTBACKUP */ | ||
| 2888 | |||
| 2889 | /** Check if the string is "empty" or "none". | ||
| 2890 | @param[in] algorithm Compression algorithm to check | ||
| 2891 | @return true if no algorithm requested */ | ||
| 2892 | 233102 | bool Compression::is_none(const char *algorithm) { | |
| 2893 | /* NULL is the same as NONE */ | ||
| 2894 |
5/6✓ Branch 0 taken 2338 times.
✓ Branch 1 taken 230764 times.
✓ Branch 2 taken 2338 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 231750 times.
✓ Branch 5 taken 1352 times.
|
235440 | if (algorithm == nullptr || *algorithm == 0 || |
| 2895 |
2/2✓ Branch 0 taken 986 times.
✓ Branch 1 taken 1352 times.
|
2338 | innobase_strcasecmp(algorithm, "none") == 0) { |
| 2896 | 231750 | return (true); | |
| 2897 | } | ||
| 2898 | |||
| 2899 | 1352 | return (false); | |
| 2900 | } | ||
| 2901 | |||
| 2902 | /** Check wether the compression algorithm is supported. | ||
| 2903 | @param[in] algorithm Compression algorithm to check | ||
| 2904 | @param[out] compression The type that algorithm maps to | ||
| 2905 | @return DB_SUCCESS or error code */ | ||
| 2906 | 232489 | dberr_t Compression::check(const char *algorithm, Compression *compression) { | |
| 2907 |
2/2✓ Branch 0 taken 231142 times.
✓ Branch 1 taken 1347 times.
|
232489 | if (is_none(algorithm)) { |
| 2908 | 231142 | compression->m_type = NONE; | |
| 2909 | |||
| 2910 |
2/2✓ Branch 0 taken 584 times.
✓ Branch 1 taken 763 times.
|
1347 | } else if (innobase_strcasecmp(algorithm, "zlib") == 0) { |
| 2911 | 584 | compression->m_type = ZLIB; | |
| 2912 | |||
| 2913 |
2/2✓ Branch 0 taken 755 times.
✓ Branch 1 taken 8 times.
|
763 | } else if (innobase_strcasecmp(algorithm, "lz4") == 0) { |
| 2914 | 755 | compression->m_type = LZ4; | |
| 2915 | |||
| 2916 | } else { | ||
| 2917 | 8 | return (DB_UNSUPPORTED); | |
| 2918 | } | ||
| 2919 | |||
| 2920 | 232481 | return (DB_SUCCESS); | |
| 2921 | } | ||
| 2922 | |||
| 2923 | /** Validate the algorithm string. | ||
| 2924 | @param[in] algorithm Compression algorithm to check | ||
| 2925 | @return DB_SUCCESS or error code */ | ||
| 2926 | 231092 | dberr_t Compression::validate(const char *algorithm) { | |
| 2927 | 231092 | Compression compression; | |
| 2928 | |||
| 2929 |
1/2✓ Branch 0 taken 231092 times.
✗ Branch 1 not taken.
|
462184 | return (check(algorithm, &compression)); |
| 2930 | } | ||
| 2931 | |||
| 2932 | 688 | bool Compression::validate(const Compression::Type type) { | |
| 2933 | 688 | bool ret = true; | |
| 2934 | |||
| 2935 |
1/2✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
|
688 | switch (type) { |
| 2936 | 688 | case NONE: | |
| 2937 | case ZLIB: | ||
| 2938 | case LZ4: | ||
| 2939 | 688 | break; | |
| 2940 | ✗ | default: | |
| 2941 | ✗ | ret = false; | |
| 2942 | ✗ | break; | |
| 2943 | } | ||
| 2944 | |||
| 2945 | 688 | return ret; | |
| 2946 | } | ||
| 2947 | |||
| 2948 | #ifndef UNIV_HOTBACKUP | ||
| 2949 | 1980475 | bool Encryption::is_empty(const char *algorithm) noexcept { | |
| 2950 | /* nullptr is the same as empty */ | ||
| 2951 | 1980475 | return algorithm == nullptr; | |
| 2952 | } | ||
| 2953 | |||
| 2954 | 1980474 | bool Encryption::is_none(const char *algorithm) noexcept { | |
| 2955 |
2/2✓ Branch 0 taken 1627127 times.
✓ Branch 1 taken 353347 times.
|
3607603 | return Encryption::is_empty(algorithm) || |
| 2956 |
2/2✓ Branch 0 taken 1589455 times.
✓ Branch 1 taken 37674 times.
|
3607603 | innobase_strcasecmp(algorithm, "n") == 0; |
| 2957 | } | ||
| 2958 | |||
| 2959 | /** Check if the string is "y" or "Y". | ||
| 2960 | @param[in] algorithm Encryption algorithm to check | ||
| 2961 | @return true if no algorithm requested */ | ||
| 2962 | 1703030 | bool Encryption::is_master_key_encryption(const char *algorithm) noexcept { | |
| 2963 | 1703030 | return innobase_strcasecmp(algorithm, "y") == 0; | |
| 2964 | } | ||
| 2965 | |||
| 2966 | /** Check if the NO algorithm was explicitly specified. | ||
| 2967 | @param[in] algorithm Encryption algorithm to check | ||
| 2968 | @return true if no algorithm explicitly requested */ | ||
| 2969 | 1568270 | bool Encryption::none_explicitly_specified(bool explicit_encryption, | |
| 2970 | const char *algorithm) noexcept { | ||
| 2971 |
2/2✓ Branch 0 taken 255776 times.
✓ Branch 1 taken 1312494 times.
|
1568270 | if (explicit_encryption) { |
| 2972 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 255776 times.
|
255776 | ut_ad(algorithm != nullptr); |
| 2973 | 255776 | return innobase_strcasecmp(algorithm, "n") == 0; | |
| 2974 | } | ||
| 2975 | 1312494 | return false; | |
| 2976 | } | ||
| 2977 | |||
| 2978 | 1721977 | bool Encryption::is_keyring(const char *algoritm) noexcept { | |
| 2979 |
4/4✓ Branch 0 taken 559786 times.
✓ Branch 1 taken 1162191 times.
✓ Branch 2 taken 307 times.
✓ Branch 3 taken 559479 times.
|
1721977 | return (algoritm != nullptr && innobase_strcasecmp(algoritm, "keyring") == 0); |
| 2980 | } | ||
| 2981 | |||
| 2982 | 1051659 | bool Encryption::is_online_encryption_on() noexcept { | |
| 2983 | 1051659 | return srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING; | |
| 2984 | } | ||
| 2985 | |||
| 2986 | // This for now excludes MK encryption ... | ||
| 2987 | 707034 | bool Encryption::should_be_keyring_encrypted(bool explicit_encryption, | |
| 2988 | const char *algorithm) noexcept { | ||
| 2989 |
4/4✓ Branch 0 taken 645623 times.
✓ Branch 1 taken 61412 times.
✓ Branch 2 taken 645470 times.
✓ Branch 3 taken 153 times.
|
1998127 | return !none_explicitly_specified(explicit_encryption, algorithm) && |
| 2990 | 645623 | (is_keyring(algorithm) || | |
| 2991 |
4/4✓ Branch 0 taken 635113 times.
✓ Branch 1 taken 10357 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 635102 times.
|
1280583 | (!Encryption::is_master_key_encryption(algorithm) && |
| 2992 | 1342148 | is_online_encryption_on())); | |
| 2993 | } | ||
| 2994 | |||
| 2995 | 341750 | dberr_t Encryption::set_algorithm(const char *option, | |
| 2996 | Encryption *encryption) noexcept { | ||
| 2997 |
2/2✓ Branch 0 taken 320993 times.
✓ Branch 1 taken 20758 times.
|
341750 | if (is_none(option)) { |
| 2998 | 320993 | encryption->m_type = NONE; | |
| 2999 | |||
| 3000 |
2/2✓ Branch 0 taken 20339 times.
✓ Branch 1 taken 420 times.
|
20758 | } else if (innobase_strcasecmp(option, "y") == 0) { |
| 3001 | 20339 | encryption->m_type = AES; | |
| 3002 | |||
| 3003 |
2/2✓ Branch 0 taken 308 times.
✓ Branch 1 taken 112 times.
|
420 | } else if (innobase_strcasecmp(option, "KEYRING") == 0) { |
| 3004 | 308 | encryption->m_type = KEYRING; | |
| 3005 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | } else if (innobase_strcasecmp(option, "ONLINE_TO_KEYRING") == 0) { |
| 3006 | ✗ | encryption->m_type = KEYRING; | |
| 3007 | } else { | ||
| 3008 | 112 | return (DB_UNSUPPORTED); | |
| 3009 | } | ||
| 3010 | |||
| 3011 | 341640 | return (DB_SUCCESS); | |
| 3012 | } | ||
| 3013 | |||
| 3014 | 340359 | dberr_t Encryption::validate(const char *option) noexcept { | |
| 3015 | 340359 | Encryption encryption; | |
| 3016 | |||
| 3017 | 340359 | return (encryption.set_algorithm(option, &encryption)); | |
| 3018 | 340361 | } | |
| 3019 | |||
| 3020 | /** Check for supported ENCRYPT := (Y | N) supported values | ||
| 3021 | @param[in] option Encryption option | ||
| 3022 | @return DB_SUCCESS or DB_UNSUPPORTED */ | ||
| 3023 | 1391 | dberr_t Encryption::validate_for_tablespace(const char *option) noexcept { | |
| 3024 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1391 times.
|
1391 | if (innobase_strcasecmp(option, "KEYRING") == 0) { |
| 3025 | ✗ | return DB_UNSUPPORTED; | |
| 3026 | } | ||
| 3027 | |||
| 3028 | 1391 | Encryption encryption; | |
| 3029 | |||
| 3030 | 1391 | return (encryption.set_algorithm(option, &encryption)); | |
| 3031 | 1391 | } | |
| 3032 | /** Compute the next autoinc value. | ||
| 3033 | |||
| 3034 | For MySQL replication the autoincrement values can be partitioned among | ||
| 3035 | the nodes. The offset is the start or origin of the autoincrement value | ||
| 3036 | for a particular node. For n nodes the increment will be n and the offset | ||
| 3037 | will be in the interval [1, n]. The formula tries to allocate the next | ||
| 3038 | value for a particular node. | ||
| 3039 | |||
| 3040 | Note: This function is also called with increment set to the number of | ||
| 3041 | values we want to reserve for multi-value inserts e.g., | ||
| 3042 | |||
| 3043 | INSERT INTO T VALUES(), (), (); | ||
| 3044 | |||
| 3045 | innobase_next_autoinc() will be called with increment set to 3 where | ||
| 3046 | autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for | ||
| 3047 | the multi-value INSERT above. | ||
| 3048 | @return the next value */ | ||
| 3049 | 9566310 | ulonglong innobase_next_autoinc( | |
| 3050 | ulonglong current, /*!< in: Current value */ | ||
| 3051 | ulonglong need, /*!< in: count of values needed */ | ||
| 3052 | ulonglong step, /*!< in: AUTOINC increment step */ | ||
| 3053 | ulonglong offset, /*!< in: AUTOINC offset */ | ||
| 3054 | ulonglong max_value) /*!< in: max value for type */ | ||
| 3055 | { | ||
| 3056 | ulonglong next_value; | ||
| 3057 | 9566310 | ulonglong block = need * step; | |
| 3058 | |||
| 3059 | /* Should never be 0. */ | ||
| 3060 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566345 times.
|
9566310 | ut_a(need > 0); |
| 3061 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566383 times.
|
9566345 | ut_a(block > 0); |
| 3062 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566425 times.
|
9566383 | ut_a(max_value > 0); |
| 3063 | |||
| 3064 | /* According to MySQL documentation, if the offset is greater than | ||
| 3065 | the step then the offset is ignored. */ | ||
| 3066 |
2/2✓ Branch 0 taken 16752 times.
✓ Branch 1 taken 9549673 times.
|
9566425 | if (offset > block) { |
| 3067 | 16752 | offset = 0; | |
| 3068 | } | ||
| 3069 | |||
| 3070 | /* Check for overflow. Current can be > max_value if the value is | ||
| 3071 | in reality a negative value.The visual studio compilers converts | ||
| 3072 | large double values automatically into unsigned long long datatype | ||
| 3073 | maximum value */ | ||
| 3074 | |||
| 3075 |
6/6✓ Branch 0 taken 9566411 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 9566406 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 9566314 times.
✓ Branch 5 taken 92 times.
|
9566425 | if (block >= max_value || offset > max_value || current >= max_value || |
| 3076 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566337 times.
|
9566314 | max_value - offset <= offset) { |
| 3077 | 88 | next_value = max_value; | |
| 3078 | } else { | ||
| 3079 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566339 times.
|
9566337 | ut_a(max_value > current); |
| 3080 | |||
| 3081 | 9566339 | ulonglong free = max_value - current; | |
| 3082 | |||
| 3083 |
4/4✓ Branch 0 taken 9566327 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 9566322 times.
|
9566339 | if (free < offset || free - offset <= block) { |
| 3084 | 17 | next_value = max_value; | |
| 3085 | } else { | ||
| 3086 | 9566322 | next_value = 0; | |
| 3087 | } | ||
| 3088 | } | ||
| 3089 | |||
| 3090 |
2/2✓ Branch 0 taken 9566327 times.
✓ Branch 1 taken 100 times.
|
9566427 | if (next_value == 0) { |
| 3091 | ulonglong next; | ||
| 3092 | |||
| 3093 |
2/2✓ Branch 0 taken 9518601 times.
✓ Branch 1 taken 47726 times.
|
9566327 | if (current > offset) { |
| 3094 | 9518601 | next = (current - offset) / step; | |
| 3095 | } else { | ||
| 3096 | 47726 | next = (offset - current) / step; | |
| 3097 | } | ||
| 3098 | |||
| 3099 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566331 times.
|
9566327 | ut_a(max_value > next); |
| 3100 | 9566331 | next_value = next * step; | |
| 3101 | /* Check for multiplication overflow. */ | ||
| 3102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566341 times.
|
9566331 | ut_a(next_value >= next); |
| 3103 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9566338 times.
|
9566341 | ut_a(max_value > next_value); |
| 3104 | |||
| 3105 | /* Check for overflow */ | ||
| 3106 |
1/2✓ Branch 0 taken 9566338 times.
✗ Branch 1 not taken.
|
9566338 | if (max_value - next_value >= block) { |
| 3107 | 9566338 | next_value += block; | |
| 3108 | |||
| 3109 |
1/2✓ Branch 0 taken 9566341 times.
✗ Branch 1 not taken.
|
9566338 | if (max_value - next_value >= offset) { |
| 3110 | 9566341 | next_value += offset; | |
| 3111 | } else { | ||
| 3112 | ✗ | next_value = max_value; | |
| 3113 | } | ||
| 3114 | } else { | ||
| 3115 | ✗ | next_value = max_value; | |
| 3116 | } | ||
| 3117 | } | ||
| 3118 | |||
| 3119 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566457 times.
|
9566438 | ut_a(next_value != 0); |
| 3120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9566459 times.
|
9566457 | ut_a(next_value <= max_value); |
| 3121 | |||
| 3122 | 9566459 | return (next_value); | |
| 3123 | } | ||
| 3124 | |||
| 3125 | /** | ||
| 3126 | Check whether given connection should log stats for slow query log InnoDB | ||
| 3127 | extensions. | ||
| 3128 | |||
| 3129 | @param[in] thd connection handle | ||
| 3130 | @return whether stats for slow query log InnoDB extensions should be logged | ||
| 3131 | */ | ||
| 3132 | 2520177506 | static bool innobase_slow_log_verbose(THD *thd) noexcept { | |
| 3133 |
4/4✓ Branch 0 taken 2112485553 times.
✓ Branch 1 taken 387661309 times.
✓ Branch 2 taken 150338 times.
✓ Branch 3 taken 2112357540 times.
|
4612658009 | return thd && thd_opt_slow_log() && |
| 3134 |
2/2✓ Branch 0 taken 2500150131 times.
✓ Branch 1 taken 20027375 times.
|
7132832246 | unlikely(thd_log_slow_verbosity(thd) & (1ULL << SLOG_V_INNODB)) && |
| 3135 |
2/2✓ Branch 0 taken 144140 times.
✓ Branch 1 taken 6198 times.
|
2520346900 | !thd_is_background_thread(thd); |
| 3136 | } | ||
| 3137 | |||
| 3138 | /** Initializes some fields in an InnoDB transaction object. */ | ||
| 3139 | 1403472171 | static void innobase_trx_init( | |
| 3140 | THD *thd, /*!< in: user thread handle */ | ||
| 3141 | trx_t *trx) /*!< in/out: InnoDB transaction handle */ | ||
| 3142 | { | ||
| 3143 |
1/2✓ Branch 0 taken 1403478385 times.
✗ Branch 1 not taken.
|
1403472171 | DBUG_TRACE; |
| 3144 |
2/4✓ Branch 0 taken 1403478517 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1403478517 times.
|
1403478385 | assert(EQ_CURRENT_THD(thd)); |
| 3145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1403478517 times.
|
1403478517 | assert(thd == trx->mysql_thd); |
| 3146 | |||
| 3147 |
1/2✓ Branch 0 taken 1403478351 times.
✗ Branch 1 not taken.
|
1403478517 | trx->check_foreigns = !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS); |
| 3148 | |||
| 3149 | 1403477908 | trx->check_unique_secondary = | |
| 3150 |
1/2✓ Branch 0 taken 1403477908 times.
✗ Branch 1 not taken.
|
1403478351 | !thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS); |
| 3151 | |||
| 3152 | 1403477908 | trx->stats.set(innobase_slow_log_verbose(thd)); | |
| 3153 | 1403475038 | } | |
| 3154 | |||
| 3155 | /** Allocates an InnoDB transaction for a MySQL handler object for DML. | ||
| 3156 | @return InnoDB transaction handle */ | ||
| 3157 | 16680054 | trx_t *innobase_trx_allocate(THD *thd) /*!< in: user thread handle */ | |
| 3158 | { | ||
| 3159 | trx_t *trx; | ||
| 3160 | |||
| 3161 |
1/2✓ Branch 0 taken 16680148 times.
✗ Branch 1 not taken.
|
16680054 | DBUG_TRACE; |
| 3162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16680148 times.
|
16680148 | assert(thd != nullptr); |
| 3163 |
2/4✓ Branch 0 taken 16680147 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16680147 times.
|
16680148 | assert(EQ_CURRENT_THD(thd)); |
| 3164 | |||
| 3165 | 16680147 | MONITOR_ATOMIC_INC(MONITOR_TRX_ALLOCATIONS); | |
| 3166 |
1/2✓ Branch 0 taken 16680158 times.
✗ Branch 1 not taken.
|
16680086 | trx = trx_allocate_for_mysql(); |
| 3167 | |||
| 3168 |
1/2✓ Branch 0 taken 16680157 times.
✗ Branch 1 not taken.
|
16680158 | rw_lock_s_lock(&purge_sys->latch, UT_LOCATION_HERE); |
| 3169 | |||
| 3170 |
3/4✓ Branch 0 taken 16680157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7881 times.
✓ Branch 3 taken 16672277 times.
|
16680157 | if (purge_sys->thds.find(thd) != purge_sys->thds.end()) { |
| 3171 | 7881 | trx->purge_sys_trx = true; | |
| 3172 | } | ||
| 3173 | |||
| 3174 |
1/2✓ Branch 0 taken 16680156 times.
✗ Branch 1 not taken.
|
16680158 | rw_lock_s_unlock(&purge_sys->latch); |
| 3175 | |||
| 3176 | 16680156 | trx->mysql_thd = thd; | |
| 3177 | |||
| 3178 |
1/2✓ Branch 0 taken 16680158 times.
✗ Branch 1 not taken.
|
16680156 | innobase_trx_init(thd, trx); |
| 3179 | |||
| 3180 | 16680158 | return trx; | |
| 3181 | 16680158 | } | |
| 3182 | |||
| 3183 | /** Gets the InnoDB transaction handle for a MySQL handler object, creates | ||
| 3184 | an InnoDB transaction struct if the corresponding MySQL thread struct still | ||
| 3185 | lacks one. | ||
| 3186 | @return InnoDB transaction handle */ | ||
| 3187 | 1403472558 | trx_t *check_trx_exists(THD *thd) /*!< in: user thread handle */ | |
| 3188 | { | ||
| 3189 | /* We request to stop master thread in srv_shutdown, which is invoked | ||
| 3190 | after DD has been shut down. Since that point of time, we must not need | ||
| 3191 | transaction objects for any reasons. */ | ||
| 3192 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 1403472743 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1403471554 times.
|
2806945301 | ut_ad(srv_shutdown_state_matches([](auto state) { |
| 3193 | return state < SRV_SHUTDOWN_MASTER_STOP || | ||
| 3194 | state == SRV_SHUTDOWN_EXIT_THREADS; | ||
| 3195 | })); | ||
| 3196 | |||
| 3197 | 1403471554 | trx_t *&trx = thd_to_trx(thd); | |
| 3198 | |||
| 3199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1403472636 times.
|
1403472524 | ut_ad(EQ_CURRENT_THD(thd)); |
| 3200 | |||
| 3201 |
2/2✓ Branch 0 taken 16679775 times.
✓ Branch 1 taken 1386792861 times.
|
1403472636 | if (trx == nullptr) { |
| 3202 | 16679775 | trx = innobase_trx_allocate(thd); | |
| 3203 | |||
| 3204 | /* User trx can be forced to rollback, | ||
| 3205 | so we unset the disable flag. */ | ||
| 3206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16679798 times.
|
16679794 | ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE); |
| 3207 | 16679798 | trx->in_innodb &= TRX_FORCE_ROLLBACK_MASK; | |
| 3208 | } else { | ||
| 3209 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1386792504 times.
|
1386792861 | ut_a(trx->magic_n == TRX_MAGIC_N); |
| 3210 | |||
| 3211 | 1386792504 | innobase_trx_init(thd, trx); | |
| 3212 | } | ||
| 3213 | |||
| 3214 | 1403478007 | return (trx); | |
| 3215 | } | ||
| 3216 | |||
| 3217 | /** Get the transaction of the current connection handle, if either exists. | ||
| 3218 | @return transaction of the current connection handle, or NULL. */ | ||
| 3219 | ✗ | trx_t *innobase_get_trx(void) { | |
| 3220 | ✗ | THD *const thd = current_thd; | |
| 3221 | ✗ | if (UNIV_UNLIKELY(!thd)) return (nullptr); | |
| 3222 | |||
| 3223 | ✗ | return (thd_to_trx(thd)); | |
| 3224 | } | ||
| 3225 | |||
| 3226 | /** Get the transaction of the current connection handle if slow query log | ||
| 3227 | InnoDB extended statistics should be collected. | ||
| 3228 | @return transaction object if statistics should be collected, or NULL. */ | ||
| 3229 | 1116718551 | trx_t *innobase_get_trx_for_slow_log(void) noexcept { | |
| 3230 | 1116718551 | THD *thd = current_thd; | |
| 3231 |
2/2✓ Branch 0 taken 1116693461 times.
✓ Branch 1 taken 43598 times.
|
1116734900 | if (UNIV_LIKELY(!innobase_slow_log_verbose(thd))) return (nullptr); |
| 3232 | 43598 | trx_t *trx = thd_to_trx(thd); | |
| 3233 |
6/6✓ Branch 0 taken 41755 times.
✓ Branch 1 taken 1843 times.
✓ Branch 2 taken 41557 times.
✓ Branch 3 taken 198 times.
✓ Branch 4 taken 41557 times.
✓ Branch 5 taken 2041 times.
|
43598 | if (trx && UNIV_UNLIKELY(trx->stats.enabled())) return (trx); |
| 3234 | 2041 | return (nullptr); | |
| 3235 | } | ||
| 3236 | |||
| 3237 | /** InnoDB transaction object that is currently associated with THD is | ||
| 3238 | replaced with that of the 2nd argument. The previous value is | ||
| 3239 | returned through the 3rd argument's buffer, unless it's NULL. When | ||
| 3240 | the buffer is not provided (value NULL) that should mean the caller | ||
| 3241 | restores previously saved association so the current trx has to be | ||
| 3242 | additionally freed from all association with MYSQL. | ||
| 3243 | |||
| 3244 | @param[in,out] thd MySQL thread handle | ||
| 3245 | @param[in] new_trx_arg replacement trx_t | ||
| 3246 | @param[in,out] ptr_trx_arg pointer to a buffer to store old trx_t */ | ||
| 3247 | 1301 | static void innodb_replace_trx_in_thd(THD *thd, void *new_trx_arg, | |
| 3248 | void **ptr_trx_arg) { | ||
| 3249 |
1/2✓ Branch 0 taken 1301 times.
✗ Branch 1 not taken.
|
1301 | DBUG_TRACE; |
| 3250 |
1/2✓ Branch 0 taken 1301 times.
✗ Branch 1 not taken.
|
1301 | trx_t *&trx = thd_to_trx(thd); |
| 3251 | |||
| 3252 |
5/8✓ Branch 0 taken 346 times.
✓ Branch 1 taken 955 times.
✓ Branch 2 taken 346 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 346 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1301 times.
|
1301 | ut_ad(new_trx_arg == nullptr || (((trx_t *)new_trx_arg)->mysql_thd == thd && |
| 3253 | !((trx_t *)new_trx_arg)->is_recovered)); | ||
| 3254 | |||
| 3255 |
2/2✓ Branch 0 taken 353 times.
✓ Branch 1 taken 948 times.
|
1301 | if (ptr_trx_arg) { |
| 3256 | 353 | *ptr_trx_arg = trx; | |
| 3257 | |||
| 3258 |
5/8✓ Branch 0 taken 347 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 347 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 347 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 353 times.
|
353 | ut_ad(trx == nullptr || (trx->mysql_thd == thd && !trx->is_recovered)); |
| 3259 | |||
| 3260 |
2/2✓ Branch 0 taken 668 times.
✓ Branch 1 taken 280 times.
|
948 | } else if (trx != nullptr) { |
| 3261 |
2/4✓ Branch 0 taken 668 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 668 times.
|
668 | ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx)); |
| 3262 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 596 times.
|
668 | if (trx->state.load(std::memory_order_relaxed) == TRX_STATE_NOT_STARTED) { |
| 3263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
|
72 | ut_ad(thd == trx->mysql_thd); |
| 3264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
|
72 | ut_ad(!trx_is_registered_for_2pc(trx)); |
| 3265 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | trx_free_for_mysql(trx); |
| 3266 | } else { | ||
| 3267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 596 times.
|
596 | ut_ad(thd == trx->mysql_thd); |
| 3268 |
2/4✓ Branch 0 taken 596 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 596 times.
|
596 | ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED)); |
| 3269 | /* The choice not to disconnect transaction when | ||
| 3270 | trx_is_redo_rseg_updated(trx) is false is copied from | ||
| 3271 | the existing detach logic for prepared XA | ||
| 3272 | transactions in innobase_close_connection(). | ||
| 3273 | If transaction did not modify anything, rolling it back doesn't modify | ||
| 3274 | the db, but lets us deregister and free the trx object to conserve | ||
| 3275 | resources, while still allowing XA COMMIT it in the future, as it | ||
| 3276 | succeeds on missing xids. */ | ||
| 3277 |
2/2✓ Branch 0 taken 588 times.
✓ Branch 1 taken 8 times.
|
596 | if (trx_is_redo_rseg_updated(trx)) { |
| 3278 |
1/2✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
|
588 | trx_disconnect_prepared(trx); |
| 3279 | } else { | ||
| 3280 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | trx_rollback_for_mysql(trx); |
| 3281 | 8 | trx_deregister_from_2pc(trx); | |
| 3282 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | trx_free_for_mysql(trx); |
| 3283 | } | ||
| 3284 | } | ||
| 3285 | } | ||
| 3286 | 1301 | trx = static_cast<trx_t *>(new_trx_arg); | |
| 3287 | 1301 | } | |
| 3288 | |||
| 3289 | /** Note that a transaction has been registered with MySQL 2PC coordinator. */ | ||
| 3290 | 115463619 | static inline void trx_register_for_2pc(trx_t *trx) /* in: transaction */ | |
| 3291 | { | ||
| 3292 | 115463619 | trx->is_registered = true; | |
| 3293 | 115463619 | } | |
| 3294 | |||
| 3295 | 22257907 | static inline void trx_deregister_from_2pc(trx_t *trx) { | |
| 3296 | 22257907 | trx->is_registered = false; | |
| 3297 | 22257907 | } | |
| 3298 | |||
| 3299 | /** Copy table flags from MySQL's HA_CREATE_INFO into an InnoDB table object. | ||
| 3300 | Those flags are stored in .frm file and end up in the MySQL table object, | ||
| 3301 | but are frequently used inside InnoDB so we keep their copies into the | ||
| 3302 | InnoDB table object. */ | ||
| 3303 | 429267 | static void innobase_copy_frm_flags_from_create_info( | |
| 3304 | dict_table_t *innodb_table, /*!< in/out: InnoDB table */ | ||
| 3305 | const HA_CREATE_INFO *create_info) /*!< in: create info */ | ||
| 3306 | { | ||
| 3307 | bool ps_on; | ||
| 3308 | bool ps_off; | ||
| 3309 | |||
| 3310 |
2/2✓ Branch 0 taken 228805 times.
✓ Branch 1 taken 200463 times.
|
429267 | if (innodb_table->is_temporary()) { |
| 3311 | /* Temp tables do not use persistent stats. */ | ||
| 3312 | 228805 | ps_on = false; | |
| 3313 | 228805 | ps_off = true; | |
| 3314 | } else { | ||
| 3315 | 200463 | ps_on = create_info->table_options & HA_OPTION_STATS_PERSISTENT; | |
| 3316 | 200463 | ps_off = create_info->table_options & HA_OPTION_NO_STATS_PERSISTENT; | |
| 3317 | } | ||
| 3318 | |||
| 3319 | 429268 | dict_stats_set_persistent(innodb_table, ps_on, ps_off); | |
| 3320 | |||
| 3321 | 429266 | dict_stats_auto_recalc_set( | |
| 3322 | 429266 | innodb_table, create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON, | |
| 3323 | 429266 | create_info->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF); | |
| 3324 | |||
| 3325 | 429267 | innodb_table->stats_sample_pages = create_info->stats_sample_pages; | |
| 3326 | 429267 | } | |
| 3327 | |||
| 3328 | /** Copy table flags from MySQL's TABLE_SHARE into an InnoDB table object. | ||
| 3329 | Those flags are stored in .frm file and end up in the MySQL table object, | ||
| 3330 | but are frequently used inside InnoDB so we keep their copies into the | ||
| 3331 | InnoDB table object. */ | ||
| 3332 | 4649373 | void innobase_copy_frm_flags_from_table_share( | |
| 3333 | dict_table_t *innodb_table, /*!< in/out: InnoDB table */ | ||
| 3334 | const TABLE_SHARE *table_share) /*!< in: table share */ | ||
| 3335 | { | ||
| 3336 | bool ps_on; | ||
| 3337 | bool ps_off; | ||
| 3338 | |||
| 3339 |
2/2✓ Branch 0 taken 349111 times.
✓ Branch 1 taken 4300262 times.
|
4649373 | if (innodb_table->is_temporary()) { |
| 3340 | /* Temp tables do not use persistent stats */ | ||
| 3341 | 349111 | ps_on = false; | |
| 3342 | 349111 | ps_off = true; | |
| 3343 | } else { | ||
| 3344 | 4300262 | ps_on = table_share->db_create_options & HA_OPTION_STATS_PERSISTENT; | |
| 3345 | 4300262 | ps_off = table_share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT; | |
| 3346 | } | ||
| 3347 | |||
| 3348 | 4649373 | dict_stats_set_persistent(innodb_table, ps_on, ps_off); | |
| 3349 | |||
| 3350 | 4649373 | dict_stats_auto_recalc_set( | |
| 3351 | 4649373 | innodb_table, table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON, | |
| 3352 | 4649373 | table_share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF); | |
| 3353 | |||
| 3354 | 4649373 | innodb_table->stats_sample_pages = table_share->stats_sample_pages; | |
| 3355 | 4649373 | } | |
| 3356 | |||
| 3357 | 408627 | int ha_innobase::srv_concurrency_enter() { | |
| 3358 | 408627 | auto err = innobase_srv_conc_enter_innodb(m_prebuilt); | |
| 3359 | |||
| 3360 | 408627 | trx_t *trx = m_prebuilt->trx; | |
| 3361 | 408627 | return convert_error_code_to_mysql(err, 0, trx->mysql_thd); | |
| 3362 | } | ||
| 3363 | |||
| 3364 | 408627 | void ha_innobase::srv_concurrency_exit() { | |
| 3365 | 408627 | innobase_srv_conc_exit_innodb(m_prebuilt); | |
| 3366 | 408627 | } | |
| 3367 | |||
| 3368 | /** Construct ha_innobase handler. */ | ||
| 3369 | |||
| 3370 | 10196990 | ha_innobase::ha_innobase(handlerton *hton, TABLE_SHARE *table_arg) | |
| 3371 | : handler(hton, table_arg), | ||
| 3372 | 10197007 | m_ds_mrr(this), | |
| 3373 | 10197005 | m_prebuilt(), | |
| 3374 | 10197005 | m_user_thd(), | |
| 3375 | 10197005 | m_int_table_flags( | |
| 3376 | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_CAN_SQL_HANDLER | | ||
| 3377 | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_PRIMARY_KEY_IN_READ_INDEX | | ||
| 3378 | HA_BINLOG_ROW_CAPABLE | HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ | | ||
| 3379 | HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT | HA_CAN_FULLTEXT_EXT | | ||
| 3380 | HA_CAN_FULLTEXT_HINTS | HA_CAN_EXPORT | HA_CAN_RTREEKEYS | | ||
| 3381 | HA_NO_READ_LOCAL_LOCK | HA_GENERATED_COLUMNS | | ||
| 3382 | HA_ATTACHABLE_TRX_COMPATIBLE | HA_CAN_INDEX_VIRTUAL_GENERATED_COLUMN | | ||
| 3383 | HA_DESCENDING_INDEX | HA_MULTI_VALUED_KEY_SUPPORT | | ||
| 3384 | HA_BLOB_PARTIAL_UPDATE | HA_SUPPORTS_GEOGRAPHIC_GEOMETRY_COLUMN | | ||
| 3385 | HA_SUPPORTS_DEFAULT_EXPRESSION | HA_ONLINE_ANALYZE), | ||
| 3386 | 10197005 | m_start_of_scan(), | |
| 3387 | 10197005 | m_stored_select_lock_type(LOCK_NONE_UNSET), | |
| 3388 | 10196990 | m_mysql_has_locked() {} | |
| 3389 | |||
| 3390 | /** Updates the user_thd field in a handle and also allocates a new InnoDB | ||
| 3391 | transaction handle if needed, and updates the transaction fields in the | ||
| 3392 | m_prebuilt struct. */ | ||
| 3393 | 1248722931 | void ha_innobase::update_thd(THD *thd) /*!< in: thd to use the handle */ | |
| 3394 | { | ||
| 3395 |
1/2✓ Branch 0 taken 1248729219 times.
✗ Branch 1 not taken.
|
1248722931 | DBUG_TRACE; |
| 3396 |
5/8✓ Branch 0 taken 1248728294 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1248726656 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66467 times.
✓ Branch 5 taken 1248660189 times.
✓ Branch 6 taken 66467 times.
✗ Branch 7 not taken.
|
1248729219 | DBUG_PRINT("ha_innobase::update_thd", |
| 3397 | ("user_thd: %p -> %p", m_user_thd, thd)); | ||
| 3398 | |||
| 3399 | /* The table should have been opened in ha_innobase::open(). */ | ||
| 3400 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1248725779 times.
|
1248726656 | assert(m_prebuilt->table->n_ref_count > 0); |
| 3401 | |||
| 3402 |
1/2✓ Branch 0 taken 1248728890 times.
✗ Branch 1 not taken.
|
1248725779 | trx_t *trx = check_trx_exists(thd); |
| 3403 | |||
| 3404 |
1/2✓ Branch 0 taken 1248725007 times.
✗ Branch 1 not taken.
|
1248728890 | TrxInInnoDB trx_in_innodb(trx); |
| 3405 | |||
| 3406 |
2/2✓ Branch 0 taken 24397928 times.
✓ Branch 1 taken 1224327079 times.
|
1248725007 | if (m_prebuilt->trx != trx) { |
| 3407 |
1/2✓ Branch 0 taken 24397802 times.
✗ Branch 1 not taken.
|
24397928 | row_update_prebuilt_trx(m_prebuilt, trx); |
| 3408 | } | ||
| 3409 | |||
| 3410 | 1248724881 | m_user_thd = thd; | |
| 3411 | |||
| 3412 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1248724881 times.
|
1248724881 | assert(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 3413 |
2/4✓ Branch 0 taken 1248725418 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1248725418 times.
|
1248724881 | assert(m_prebuilt->trx == thd_to_trx(m_user_thd)); |
| 3414 | 1248725418 | } | |
| 3415 | |||
| 3416 | /** Updates the user_thd field in a handle and also allocates a new InnoDB | ||
| 3417 | transaction handle if needed, and updates the transaction fields in the | ||
| 3418 | m_prebuilt struct. */ | ||
| 3419 | |||
| 3420 | 1004191520 | void ha_innobase::update_thd() { | |
| 3421 | 1004191520 | THD *thd = ha_thd(); | |
| 3422 | |||
| 3423 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1004190847 times.
|
1004192379 | ut_ad(EQ_CURRENT_THD(thd)); |
| 3424 | 1004190847 | update_thd(thd); | |
| 3425 | 1004193831 | } | |
| 3426 | |||
| 3427 | /** Registers an InnoDB transaction with the MySQL 2PC coordinator, so that | ||
| 3428 | the MySQL XA code knows to call the InnoDB prepare and commit, or rollback | ||
| 3429 | for the transaction. This MUST be called for every transaction for which | ||
| 3430 | the user may call commit or rollback. Calling this several times to register | ||
| 3431 | the same transaction is allowed, too. This function also registers the | ||
| 3432 | current SQL statement. */ | ||
| 3433 | 115463523 | void innobase_register_trx(handlerton *hton, /* in: Innobase handlerton */ | |
| 3434 | THD *thd, /* in: MySQL thd (connection) object */ | ||
| 3435 | trx_t *trx) /* in: transaction to register */ | ||
| 3436 | { | ||
| 3437 |
1/2✓ Branch 0 taken 115463918 times.
✗ Branch 1 not taken.
|
115463523 | const ulonglong trx_id = static_cast<ulonglong>(trx_get_id_for_print(trx)); |
| 3438 | |||
| 3439 |
1/2✓ Branch 0 taken 115464537 times.
✗ Branch 1 not taken.
|
115463918 | trans_register_ha(thd, false, hton, &trx_id); |
| 3440 | |||
| 3441 |
4/4✓ Branch 0 taken 21634220 times.
✓ Branch 1 taken 93829364 times.
✓ Branch 2 taken 1114947 times.
✓ Branch 3 taken 114349058 times.
|
137099178 | if (!trx_is_registered_for_2pc(trx) && |
| 3442 |
3/4✓ Branch 0 taken 21634641 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1114925 times.
✓ Branch 3 taken 20519716 times.
|
21634220 | thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 3443 |
1/2✓ Branch 0 taken 1115058 times.
✗ Branch 1 not taken.
|
1114947 | trans_register_ha(thd, true, hton, &trx_id); |
| 3444 | } | ||
| 3445 | |||
| 3446 | 115464116 | trx_register_for_2pc(trx); | |
| 3447 | 115463867 | } | |
| 3448 | |||
| 3449 | /** Quote a standard SQL identifier like tablespace, index or column name. | ||
| 3450 | @param[in] file output stream | ||
| 3451 | @param[in] trx InnoDB transaction, or NULL | ||
| 3452 | @param[in] id identifier to quote */ | ||
| 3453 | 1038 | void innobase_quote_identifier(FILE *file, trx_t *trx, const char *id) { | |
| 3454 | const int q = | ||
| 3455 |
1/2✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
|
1038 | trx != nullptr && trx->mysql_thd != nullptr |
| 3456 |
1/2✓ Branch 0 taken 1038 times.
✗ Branch 1 not taken.
|
2076 | ? get_quote_char_for_identifier(trx->mysql_thd, id, strlen(id)) |
| 3457 | 1038 | : '`'; | |
| 3458 | |||
| 3459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1038 times.
|
1038 | if (q == EOF) { |
| 3460 | ✗ | fputs(id, file); | |
| 3461 | } else { | ||
| 3462 | 1038 | putc(q, file); | |
| 3463 | |||
| 3464 |
2/2✓ Branch 0 taken 4518 times.
✓ Branch 1 taken 1038 times.
|
5556 | while (int c = *id++) { |
| 3465 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4518 times.
|
4518 | if (c == q) { |
| 3466 | ✗ | putc(c, file); | |
| 3467 | } | ||
| 3468 | 4518 | putc(c, file); | |
| 3469 | 4518 | } | |
| 3470 | |||
| 3471 | 1038 | putc(q, file); | |
| 3472 | } | ||
| 3473 | 1038 | } | |
| 3474 | |||
| 3475 | /** Convert a table name to the MySQL system_charset_info (UTF-8) | ||
| 3476 | and quote it. | ||
| 3477 | @param[out] buf buffer for converted identifier | ||
| 3478 | @param[in] buflen length of buf, in bytes | ||
| 3479 | @param[in] id identifier to convert | ||
| 3480 | @param[in] idlen length of id, in bytes | ||
| 3481 | @param[in] thd MySQL connection thread, or NULL | ||
| 3482 | @return pointer to the end of buf */ | ||
| 3483 | 31144 | static char *innobase_convert_identifier(char *buf, ulint buflen, | |
| 3484 | const char *id, ulint idlen, | ||
| 3485 | THD *thd) { | ||
| 3486 | 31144 | const char *s = id; | |
| 3487 | |||
| 3488 | char nz[MAX_TABLE_NAME_LEN + 1]; | ||
| 3489 | char nz2[MAX_TABLE_NAME_LEN + 1]; | ||
| 3490 | |||
| 3491 | /* Decode the table name. The MySQL function expects | ||
| 3492 | a NUL-terminated string. The input and output strings | ||
| 3493 | buffers must not be shared. */ | ||
| 3494 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31144 times.
|
31144 | ut_a(idlen <= MAX_TABLE_NAME_LEN); |
| 3495 | 31144 | memcpy(nz, id, idlen); | |
| 3496 | 31144 | nz[idlen] = 0; | |
| 3497 | |||
| 3498 | 31144 | s = nz2; | |
| 3499 | idlen = | ||
| 3500 |
1/2✓ Branch 0 taken 31144 times.
✗ Branch 1 not taken.
|
31144 | explain_filename(thd, nz, nz2, sizeof nz2, EXPLAIN_PARTITIONS_AS_COMMENT); |
| 3501 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 31138 times.
|
31144 | if (idlen > buflen) { |
| 3502 | 6 | idlen = buflen; | |
| 3503 | } | ||
| 3504 | 31144 | memcpy(buf, s, idlen); | |
| 3505 | 31144 | return (buf + idlen); | |
| 3506 | } | ||
| 3507 | |||
| 3508 | /** Convert a table name to the MySQL system_charset_info (UTF-8). | ||
| 3509 | @return pointer to the end of buf */ | ||
| 3510 | 15809 | char *innobase_convert_name( | |
| 3511 | char *buf, /*!< out: buffer for converted identifier */ | ||
| 3512 | ulint buflen, /*!< in: length of buf, in bytes */ | ||
| 3513 | const char *id, /*!< in: table name to convert */ | ||
| 3514 | ulint idlen, /*!< in: length of id, in bytes */ | ||
| 3515 | THD *thd) /*!< in: MySQL connection thread, or NULL */ | ||
| 3516 | { | ||
| 3517 | 15809 | char *s = buf; | |
| 3518 | 15809 | const char *bufend = buf + buflen; | |
| 3519 | |||
| 3520 | 15809 | const char *slash = (const char *)memchr(id, '/', idlen); | |
| 3521 | |||
| 3522 |
2/2✓ Branch 0 taken 468 times.
✓ Branch 1 taken 15341 times.
|
15809 | if (slash == nullptr) { |
| 3523 | 468 | return (innobase_convert_identifier(buf, buflen, id, idlen, thd)); | |
| 3524 | } | ||
| 3525 | |||
| 3526 | /* Print the database name and table name separately. */ | ||
| 3527 | 15341 | s = innobase_convert_identifier(s, bufend - s, id, slash - id, thd); | |
| 3528 |
2/2✓ Branch 0 taken 15335 times.
✓ Branch 1 taken 6 times.
|
15341 | if (s < bufend) { |
| 3529 | 15335 | *s++ = '.'; | |
| 3530 | 15335 | s = innobase_convert_identifier(s, bufend - s, slash + 1, | |
| 3531 | 15335 | idlen - (slash - id) - 1, thd); | |
| 3532 | } | ||
| 3533 | |||
| 3534 | 15341 | return (s); | |
| 3535 | } | ||
| 3536 | |||
| 3537 | /** A wrapper function of innobase_convert_name(), convert a table name | ||
| 3538 | to the MySQL system_charset_info (UTF-8) and quote it if needed. | ||
| 3539 | @param[out] buf Buffer for converted identifier | ||
| 3540 | @param[in] buflen Length of buf, in bytes | ||
| 3541 | @param[in] name Table name to format */ | ||
| 3542 | 181 | void innobase_format_name(char *buf, ulint buflen, const char *name) { | |
| 3543 | const char *bufend; | ||
| 3544 | |||
| 3545 | 181 | bufend = innobase_convert_name(buf, buflen, name, strlen(name), nullptr); | |
| 3546 | |||
| 3547 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
|
181 | ut_ad((ulint)(bufend - buf) < buflen); |
| 3548 | |||
| 3549 | 181 | buf[bufend - buf] = '\0'; | |
| 3550 | 181 | } | |
| 3551 | |||
| 3552 | /** Determines if the currently running transaction has been interrupted. | ||
| 3553 | @return true if interrupted */ | ||
| 3554 | 411305509 | bool trx_is_interrupted(const trx_t *trx) /*!< in: transaction */ | |
| 3555 | { | ||
| 3556 |
6/6✓ Branch 0 taken 411132933 times.
✓ Branch 1 taken 172576 times.
✓ Branch 2 taken 411132897 times.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 411132520 times.
|
411305509 | return (trx && trx->mysql_thd && thd_killed(trx->mysql_thd)); |
| 3557 | } | ||
| 3558 | |||
| 3559 | /** Determines if the currently running transaction is in strict mode. | ||
| 3560 | @return true if strict */ | ||
| 3561 | 374181 | bool trx_is_strict(trx_t *trx) /*!< in: transaction */ | |
| 3562 | { | ||
| 3563 | /* Relax strict check if table is in truncate create table */ | ||
| 3564 |
4/6✓ Branch 0 taken 374181 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 374181 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 370647 times.
✓ Branch 5 taken 3534 times.
|
744828 | return (trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode) && |
| 3565 |
2/2✓ Branch 0 taken 303604 times.
✓ Branch 1 taken 67043 times.
|
744828 | (!trx->in_truncate)); |
| 3566 | } | ||
| 3567 | |||
| 3568 | /** Resets some fields of a m_prebuilt struct. The template is used in fast | ||
| 3569 | retrieval of just those column values MySQL needs in its processing. */ | ||
| 3570 | 449527008 | void ha_innobase::reset_template(void) { | |
| 3571 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 449528424 times.
|
449527008 | ut_ad(m_prebuilt->magic_n == ROW_PREBUILT_ALLOCATED); |
| 3572 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 449528701 times.
|
449528424 | ut_ad(m_prebuilt->magic_n2 == m_prebuilt->magic_n); |
| 3573 | |||
| 3574 | /* Force table to be freed in close_thread_table(). */ | ||
| 3575 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 449528742 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
449528701 | DBUG_EXECUTE_IF( |
| 3576 | "free_table_in_fts_query", | ||
| 3577 | if (m_prebuilt->in_fts_query) { table->invalidate_dict(); }); | ||
| 3578 | |||
| 3579 | 449528742 | m_prebuilt->keep_other_fields_on_keyread = 0; | |
| 3580 | 449528742 | m_prebuilt->read_just_key = 0; | |
| 3581 | 449528742 | m_prebuilt->in_fts_query = false; | |
| 3582 | 449528742 | m_prebuilt->m_end_range = false; | |
| 3583 | |||
| 3584 | /* Reset index condition pushdown state. */ | ||
| 3585 |
2/2✓ Branch 0 taken 2133 times.
✓ Branch 1 taken 449526609 times.
|
449528742 | if (m_prebuilt->idx_cond) { |
| 3586 | 2133 | m_prebuilt->idx_cond = false; | |
| 3587 | 2133 | m_prebuilt->idx_cond_n_cols = 0; | |
| 3588 | /* Invalidate m_prebuilt->mysql_template | ||
| 3589 | in ha_innobase::write_row(). */ | ||
| 3590 | 2133 | m_prebuilt->template_type = ROW_MYSQL_NO_TEMPLATE; | |
| 3591 | } | ||
| 3592 | 449528742 | } | |
| 3593 | |||
| 3594 | /** Call this when you have opened a new table handle in HANDLER, before you | ||
| 3595 | call index_read_map() etc. Actually, we can let the cursor stay open even | ||
| 3596 | over a transaction commit! Then you should call this before every operation, | ||
| 3597 | fetch next etc. This function inits the necessary things even after a | ||
| 3598 | transaction commit. */ | ||
| 3599 | |||
| 3600 | 41600 | void ha_innobase::init_table_handle_for_HANDLER(void) { | |
| 3601 | /* If current thd does not yet have a trx struct, create one. | ||
| 3602 | If the current handle does not yet have a m_prebuilt struct, create | ||
| 3603 | one. Update the trx pointers in the m_prebuilt struct. Normally | ||
| 3604 | this operation is done in external_lock. */ | ||
| 3605 | |||
| 3606 |
2/4✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41600 times.
✗ Branch 3 not taken.
|
41600 | update_thd(ha_thd()); |
| 3607 | |||
| 3608 | /* Initialize the m_prebuilt struct much like it would be inited in | ||
| 3609 | external_lock */ | ||
| 3610 | |||
| 3611 |
1/2✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
|
41600 | innobase_srv_conc_force_exit_innodb(m_prebuilt->trx); |
| 3612 | |||
| 3613 | /* If the transaction is not started yet, start it */ | ||
| 3614 | |||
| 3615 |
1/2✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
|
41600 | trx_start_if_not_started_xa(m_prebuilt->trx, false, UT_LOCATION_HERE); |
| 3616 | |||
| 3617 |
1/2✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
|
41600 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 3618 | |||
| 3619 | /* Assign a read view if the transaction does not have it yet */ | ||
| 3620 | |||
| 3621 |
1/2✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
|
41600 | trx_assign_read_view(m_prebuilt->trx); |
| 3622 | |||
| 3623 |
1/2✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
|
41600 | innobase_register_trx(ht, m_user_thd, m_prebuilt->trx); |
| 3624 | |||
| 3625 | /* We did the necessary inits in this function, no need to repeat them | ||
| 3626 | in row_search_for_mysql */ | ||
| 3627 | |||
| 3628 | 41600 | m_prebuilt->sql_stat_start = false; | |
| 3629 | |||
| 3630 | /* We let HANDLER always to do the reads as consistent reads, even | ||
| 3631 | if the trx isolation level would have been specified as SERIALIZABLE */ | ||
| 3632 | |||
| 3633 | 41600 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 3634 | 41600 | m_prebuilt->select_mode = SELECT_ORDINARY; | |
| 3635 | 41600 | m_stored_select_lock_type = LOCK_NONE; | |
| 3636 | |||
| 3637 | /* Always fetch all columns in the index record */ | ||
| 3638 | |||
| 3639 | 41600 | m_prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS; | |
| 3640 | |||
| 3641 | /* We want always to fetch all columns in the whole row? Or do | ||
| 3642 | we???? */ | ||
| 3643 | |||
| 3644 | 41600 | m_prebuilt->used_in_HANDLER = true; | |
| 3645 | |||
| 3646 |
1/2✓ Branch 0 taken 41600 times.
✗ Branch 1 not taken.
|
41600 | reset_template(); |
| 3647 | 41600 | } | |
| 3648 | |||
| 3649 | /** Free any resources that were allocated and return failure. | ||
| 3650 | @return always return 1 */ | ||
| 3651 | 104 | static int innodb_init_abort() { | |
| 3652 |
1/2✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
|
104 | DBUG_TRACE; |
| 3653 |
1/2✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
|
104 | srv_shutdown_exit_threads(); |
| 3654 |
1/2✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
|
104 | innodb_space_shutdown(); |
| 3655 |
1/2✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
|
104 | innobase::component_services::deinitialize_service_handles(); |
| 3656 |
1/2✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
|
104 | release_plugin_services(); |
| 3657 | 104 | return 1; | |
| 3658 | 104 | } | |
| 3659 | |||
| 3660 | /** Open or create InnoDB data files. | ||
| 3661 | @param[in] dict_init_mode whether to create or open the files | ||
| 3662 | @param[in,out] tablespaces predefined tablespaces created by the DDSE | ||
| 3663 | @return 0 on success, 1 on failure */ | ||
| 3664 | [[nodiscard]] static int innobase_init_files( | ||
| 3665 | dict_init_mode_t dict_init_mode, | ||
| 3666 | List<const Plugin_tablespace> *tablespaces, | ||
| 3667 | bool &is_dd_encrypted); | ||
| 3668 | |||
| 3669 | /** Initialize InnoDB for being used to store the DD tables. | ||
| 3670 | Create the required files according to the dict_init_mode. | ||
| 3671 | Create strings representing the required DDSE tables, i.e., | ||
| 3672 | tables that InnoDB expects to exist in the DD, | ||
| 3673 | and add them to the appropriate out parameter. | ||
| 3674 | |||
| 3675 | @param[in] dict_init_mode How to initialize files | ||
| 3676 | |||
| 3677 | @param[in] version Target DD version if a new server | ||
| 3678 | is being installed. | ||
| 3679 | 0 if restarting an existing server. | ||
| 3680 | |||
| 3681 | @param[out] tables List of SQL DDL statements | ||
| 3682 | for creating DD tables that | ||
| 3683 | are needed by the DDSE. | ||
| 3684 | |||
| 3685 | @param[out] tablespaces List of meta data for predefined | ||
| 3686 | tablespaces created by the DDSE. | ||
| 3687 | |||
| 3688 | @retval true An error occurred. | ||
| 3689 | @retval false Success - no errors. */ | ||
| 3690 | static bool innobase_ddse_dict_init(dict_init_mode_t dict_init_mode, | ||
| 3691 | uint version, | ||
| 3692 | List<const dd::Object_table> *tables, | ||
| 3693 | List<const Plugin_tablespace> *tablespaces); | ||
| 3694 | |||
| 3695 | /** Save the state of undo tablespaces from the dd to the undo::Tablespace | ||
| 3696 | @param[in] space_id tablespace ID | ||
| 3697 | @param[in] dd_space dd::Tablespace object | ||
| 3698 | @return true if success and false if the undo tablespace state is not saved. */ | ||
| 3699 | 23335 | bool apply_dd_undo_state(space_id_t space_id, const dd::Tablespace *dd_space) { | |
| 3700 | 23335 | bool success = true; | |
| 3701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23335 times.
|
23335 | if (!fsp_is_undo_tablespace(space_id)) { |
| 3702 | ✗ | return (success); | |
| 3703 | } | ||
| 3704 | |||
| 3705 | /* Get the state of undo tablespaces from the DD. */ | ||
| 3706 | 23335 | dd_space_states state = dd_tablespace_get_state_enum(dd_space, space_id); | |
| 3707 | |||
| 3708 | 23335 | undo::spaces->s_lock(); | |
| 3709 | |||
| 3710 | 23335 | space_id_t space_num = undo::id2num(space_id); | |
| 3711 | 23335 | undo::Tablespace *undo_space = undo::spaces->find(space_num); | |
| 3712 | |||
| 3713 |
3/5✓ Branch 0 taken 23273 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
23335 | switch (state) { |
| 3714 | 23273 | case DD_SPACE_STATE__LAST: | |
| 3715 | /* If the "state" key is missing the DD might have been built with | ||
| 3716 | an older version. */ | ||
| 3717 | case DD_SPACE_STATE_ACTIVE: | ||
| 3718 | /* Explicit undo spaces with no undo logs are set empty during | ||
| 3719 | startup to avoid getting undo. */ | ||
| 3720 |
2/2✓ Branch 0 taken 225 times.
✓ Branch 1 taken 23048 times.
|
23273 | if (undo_space->is_empty()) { |
| 3721 | 225 | undo_space->set_active(); | |
| 3722 | } | ||
| 3723 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23273 times.
|
23273 | ut_ad(undo_space->is_active()); |
| 3724 | 23273 | break; | |
| 3725 | 2 | case DD_SPACE_STATE_INACTIVE: | |
| 3726 | 2 | undo_space->set_inactive_explicit(); | |
| 3727 | 2 | srv_wake_purge_thread_if_not_active(); | |
| 3728 | |||
| 3729 | 2 | break; | |
| 3730 | 60 | case DD_SPACE_STATE_EMPTY: | |
| 3731 | 60 | undo_space->set_empty(); | |
| 3732 | 60 | break; | |
| 3733 | ✗ | case DD_SPACE_STATE_NORMAL: | |
| 3734 | case DD_SPACE_STATE_DISCARDED: | ||
| 3735 | case DD_SPACE_STATE_CORRUPTED: | ||
| 3736 | ✗ | success = false; | |
| 3737 | ✗ | break; | |
| 3738 | } | ||
| 3739 | |||
| 3740 | 23335 | undo::spaces->s_unlock(); | |
| 3741 | |||
| 3742 | 23335 | return (success); | |
| 3743 | } | ||
| 3744 | |||
| 3745 | /** Initialize the set of hard coded DD table ids. | ||
| 3746 | @param[in] dd_table_id Table id of DD table. */ | ||
| 3747 | static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id); | ||
| 3748 | |||
| 3749 | /** Validate the DD tablespace data against what's read during the | ||
| 3750 | directory scan on startup. */ | ||
| 3751 | class Validate_files { | ||
| 3752 | using DD_tablespaces = std::vector<const dd::Tablespace *>; | ||
| 3753 | using Const_iter = DD_tablespaces::const_iterator; | ||
| 3754 | |||
| 3755 | public: | ||
| 3756 | /** Constructor */ | ||
| 3757 | 11531 | Validate_files() | |
| 3758 | 11531 | : m_mutex(), | |
| 3759 | 11531 | m_space_max_id(), | |
| 3760 | 11531 | m_n_to_check(), | |
| 3761 | 11531 | m_n_threads(), | |
| 3762 | 11531 | m_start_time(std::chrono::steady_clock::time_point{}), | |
| 3763 | 11531 | m_n_validated(), | |
| 3764 | 11531 | m_n_skipped(), | |
| 3765 | 11531 | m_n_moved(), | |
| 3766 | 11531 | m_n_missing(), | |
| 3767 | 11531 | m_n_deleted(), | |
| 3768 | 11531 | m_n_errors() {} | |
| 3769 | |||
| 3770 | /** Validate the discovered tablespaces against the DD and attempt to open | ||
| 3771 | any DD tablespace not already open using a Parallel For Loop (par_for). | ||
| 3772 | @param[in] tablespaces Tablespace files read from the DD | ||
| 3773 | @return DB_SUCCESS if all OK */ | ||
| 3774 | [[nodiscard]] dberr_t validate(const DD_tablespaces &tablespaces); | ||
| 3775 | |||
| 3776 | private: | ||
| 3777 | /** Validate a range of tablespaces from the DD. | ||
| 3778 | 1. Compare the discovered files against those known to the dictionary. | ||
| 3779 | 2. Open any tablespace known to the DD but not discovered and opened | ||
| 3780 | from the known directories. | ||
| 3781 | 3. Update the DD if a tablespace has moved. | ||
| 3782 | 4. Update the DD if an undo tablespace was truncated and replaced. | ||
| 3783 | 5. If innodb_validate_tablespace_paths is set and this is not called | ||
| 3784 | while in recovery, only validate undo tablespaces. | ||
| 3785 | 6. Track the number of skipped, moved, missing and deleted tablespaces. | ||
| 3786 | 7. Return failure for any unexpected error. | ||
| 3787 | @param[in] begin Start of the slice | ||
| 3788 | @param[in] end End of the slice | ||
| 3789 | @param[in] thread_id Thread ID */ | ||
| 3790 | void check(const Const_iter &begin, const Const_iter &end, size_t thread_id); | ||
| 3791 | |||
| 3792 | /** @return true if there were failures. */ | ||
| 3793 | 23062 | bool failed() const { return (m_n_errors.load() != 0); } | |
| 3794 | |||
| 3795 | /** @return the maximum tablespace ID found. */ | ||
| 3796 | 11531 | space_id_t get_space_max_id() const { return (m_space_max_id); } | |
| 3797 | |||
| 3798 | private: | ||
| 3799 | /** Mutex protecting the parallel check. */ | ||
| 3800 | std::mutex m_mutex; | ||
| 3801 | |||
| 3802 | /** Maximum tablespace ID found. */ | ||
| 3803 | space_id_t m_space_max_id; | ||
| 3804 | |||
| 3805 | /** Number of tablespaces to check. */ | ||
| 3806 | size_t m_n_to_check; | ||
| 3807 | |||
| 3808 | /** Number of threads used in the parallel for. */ | ||
| 3809 | size_t m_n_threads; | ||
| 3810 | |||
| 3811 | /** The time when Validate_files::validate() starts or the last time | ||
| 3812 | one of the threads reported progress. */ | ||
| 3813 | std::atomic<std::chrono::steady_clock::time_point> m_start_time; | ||
| 3814 | static_assert(decltype(m_start_time)::is_always_lock_free); | ||
| 3815 | |||
| 3816 | /** Number of tablespaces validated. */ | ||
| 3817 | std::atomic_size_t m_n_validated; | ||
| 3818 | |||
| 3819 | /** Number of tablespaces skipped. */ | ||
| 3820 | std::atomic_size_t m_n_skipped; | ||
| 3821 | |||
| 3822 | /** Number of tablespaces moved. */ | ||
| 3823 | std::atomic_size_t m_n_moved; | ||
| 3824 | |||
| 3825 | /** Number of tablespaces missing. */ | ||
| 3826 | std::atomic_size_t m_n_missing; | ||
| 3827 | |||
| 3828 | /** Number of tablespaces deleted. */ | ||
| 3829 | std::atomic_size_t m_n_deleted; | ||
| 3830 | |||
| 3831 | /** Number of threads that failed. */ | ||
| 3832 | std::atomic_size_t m_n_errors; | ||
| 3833 | }; | ||
| 3834 | |||
| 3835 | 11531 | void Validate_files::check(const Const_iter &begin, const Const_iter &end, | |
| 3836 | size_t thread_id) { | ||
| 3837 | 11531 | const auto sys_space_name = dict_sys_t::s_sys_space_name; | |
| 3838 | |||
| 3839 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | auto heap = mem_heap_create(FN_REFLEN * 2 + 1, UT_LOCATION_HERE); |
| 3840 | |||
| 3841 | /* If the setting for innodb_validate_tablespace_paths is NO and we are | ||
| 3842 | not in recovery, then only validate undo tablespaces. */ | ||
| 3843 | 11531 | const bool ibd_validate = | |
| 3844 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 11517 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 11 times.
|
11531 | srv_validate_tablespace_paths || recv_needed_recovery; |
| 3845 | |||
| 3846 | 11531 | std::string prefix; | |
| 3847 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
|
11531 | if (m_n_threads > 0) { |
| 3848 | ✗ | std::ostringstream msg; | |
| 3849 | ✗ | msg << "Thread# " << thread_id << " - "; | |
| 3850 | ✗ | prefix = msg.str(); | |
| 3851 | } | ||
| 3852 | |||
| 3853 |
2/2✓ Branch 0 taken 127913 times.
✓ Branch 1 taken 11531 times.
|
139444 | for (auto it = begin; it != end; ++it) { |
| 3854 | 127913 | const auto &dd_tablespace = *it; | |
| 3855 | |||
| 3856 |
3/6✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127913 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 127913 times.
|
127913 | if (std::chrono::steady_clock::now() - m_start_time.load() >= |
| 3857 | PRINT_INTERVAL) { | ||
| 3858 | ✗ | m_start_time = std::chrono::steady_clock::now(); | |
| 3859 | |||
| 3860 | ✗ | std::ostringstream msg; | |
| 3861 | |||
| 3862 | ✗ | if (m_n_threads) { | |
| 3863 | ✗ | msg << m_n_threads << "threads have validated "; | |
| 3864 | } else { | ||
| 3865 | ✗ | msg << "Validated "; | |
| 3866 | } | ||
| 3867 | |||
| 3868 | ✗ | msg << m_n_validated << " out of " << m_n_to_check | |
| 3869 | ✗ | << " tablespaces so far."; | |
| 3870 | |||
| 3871 | ✗ | if (m_n_skipped > 0) { | |
| 3872 | ✗ | msg << " Skipped=" << m_n_skipped << "."; | |
| 3873 | } | ||
| 3874 | ✗ | if (m_n_moved > 0) { | |
| 3875 | ✗ | msg << " Moved=" << m_n_moved << "."; | |
| 3876 | } | ||
| 3877 | ✗ | if (m_n_missing > 0) { | |
| 3878 | ✗ | msg << " Missing=" << m_n_missing << "."; | |
| 3879 | } | ||
| 3880 | ✗ | if (m_n_deleted > 0) { | |
| 3881 | ✗ | msg << " Deleted=" << m_n_deleted << "."; | |
| 3882 | } | ||
| 3883 | |||
| 3884 | ✗ | ib::info(ER_IB_MSG_525) << msg.str(); | |
| 3885 | } | ||
| 3886 | |||
| 3887 |
3/6✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127913 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 127913 times.
|
127913 | if (dd_tablespace->engine() != innobase_hton_name) { |
| 3888 | ✗ | ++m_n_skipped; | |
| 3889 | 61977 | continue; | |
| 3890 | } | ||
| 3891 | |||
| 3892 | 127913 | bool is_enc_in_progress{false}; | |
| 3893 |
1/2✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
|
127913 | const auto &p = dd_tablespace->se_private_data(); |
| 3894 |
1/2✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
|
127913 | const auto &o = dd_tablespace->options(); |
| 3895 |
1/2✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
|
127913 | const char *space_name = dd_tablespace->name().c_str(); |
| 3896 | 127913 | const auto se_key_value = dd_space_key_strings; | |
| 3897 | |||
| 3898 | /* There should be exactly one file name associated | ||
| 3899 | with each InnoDB tablespace, except innodb_system */ | ||
| 3900 | |||
| 3901 | space_id_t space_id; | ||
| 3902 |
3/6✓ Branch 0 taken 127913 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127913 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 127913 times.
|
127913 | if (p.get(se_key_value[DD_SPACE_ID], &space_id)) { |
| 3903 | /* Failed to fetch the tablespace ID */ | ||
| 3904 | ✗ | ++m_n_errors; | |
| 3905 | ✗ | break; | |
| 3906 | } | ||
| 3907 | |||
| 3908 | /* If --innodb_validate_tablespace_paths=OFF and | ||
| 3909 | startup is not in recovery, then skip all IBD files. */ | ||
| 3910 |
7/8✓ Branch 0 taken 199 times.
✓ Branch 1 taken 127714 times.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 177 times.
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 177 times.
✓ Branch 7 taken 127736 times.
|
127913 | if (!ibd_validate && !fsp_is_undo_tablespace(space_id)) { |
| 3911 | 177 | ++m_n_skipped; | |
| 3912 | 177 | continue; | |
| 3913 | } | ||
| 3914 | |||
| 3915 | /* Do not open a discovered tablespace that is currently discarded. | ||
| 3916 | It will be opened properly when it is imported. */ | ||
| 3917 |
1/2✓ Branch 0 taken 127736 times.
✗ Branch 1 not taken.
|
127736 | dd_space_states dd_state = dd_tablespace_get_state_enum(&p, space_id); |
| 3918 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 127658 times.
|
127736 | if (dd_state == DD_SPACE_STATE_DISCARDED) { |
| 3919 | 78 | ++m_n_skipped; | |
| 3920 | 78 | continue; | |
| 3921 | } | ||
| 3922 | |||
| 3923 |
5/10✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127658 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 127657 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 127658 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
255317 | if (p.exists(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS]) && |
| 3924 |
6/12✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 127657 times.
✓ Branch 8 taken 127658 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
127659 | p.get(se_key_value[DD_SPACE_ONLINE_ENC_PROGRESS], |
| 3925 | &is_enc_in_progress)) { | ||
| 3926 | ✗ | ++m_n_errors; | |
| 3927 | ✗ | break; | |
| 3928 | } | ||
| 3929 | |||
| 3930 | /* Get the spacename for this tablespace from the DD. */ | ||
| 3931 |
4/6✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 127642 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 127658 times.
|
127674 | if (dd_tablespace->files().size() != 1 && |
| 3932 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | strcmp(space_name, sys_space_name) != 0) { |
| 3933 | /* Only the InnoDB system tablespace has support for | ||
| 3934 | multiple files per tablespace. For historial reasons. */ | ||
| 3935 | ✗ | ++m_n_errors; | |
| 3936 | ✗ | break; | |
| 3937 | } | ||
| 3938 | |||
| 3939 | { | ||
| 3940 |
1/2✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
|
127658 | std::lock_guard<std::mutex> guard(m_mutex); |
| 3941 | |||
| 3942 |
6/6✓ Branch 0 taken 81268 times.
✓ Branch 1 taken 46390 times.
✓ Branch 2 taken 69321 times.
✓ Branch 3 taken 11947 times.
✓ Branch 4 taken 69321 times.
✓ Branch 5 taken 58337 times.
|
127658 | if (!dict_sys_t::is_reserved(space_id) && space_id > m_space_max_id) { |
| 3943 | /* Currently try to find the max space_id only. | ||
| 3944 | It should be able to reuse the deleted smaller ones later */ | ||
| 3945 | 69321 | m_space_max_id = space_id; | |
| 3946 | } | ||
| 3947 | 127658 | } | |
| 3948 | |||
| 3949 | /* System and temp files are tracked and opened separately. | ||
| 3950 | Consider them validated. */ | ||
| 3951 |
3/4✓ Branch 0 taken 127658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23040 times.
✓ Branch 3 taken 104618 times.
|
127658 | if (fsp_is_system_or_temp_tablespace(space_id)) { |
| 3952 | 23040 | ++m_n_validated; | |
| 3953 | 23040 | continue; | |
| 3954 | } | ||
| 3955 | |||
| 3956 | /* Get the filename for this tablespace from the DD. */ | ||
| 3957 |
3/6✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 104618 times.
✗ Branch 5 not taken.
|
104618 | const auto file = *dd_tablespace->files().begin(); |
| 3958 |
2/4✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
|
104618 | std::string dd_path{file->filename().c_str()}; |
| 3959 | 104618 | const char *filename = dd_path.c_str(); | |
| 3960 | |||
| 3961 | /* If the trunc log file is still around, this undo tablespace needs to be | ||
| 3962 | rebuilt now. */ | ||
| 3963 |
3/4✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23350 times.
✓ Branch 3 taken 81268 times.
|
104618 | if (fsp_is_undo_tablespace(space_id)) { |
| 3964 |
1/2✓ Branch 0 taken 23350 times.
✗ Branch 1 not taken.
|
23350 | mutex_enter(&undo::ddl_mutex); |
| 3965 |
1/2✓ Branch 0 taken 23350 times.
✗ Branch 1 not taken.
|
23350 | dberr_t err = srv_undo_tablespace_fixup(space_name, filename, space_id); |
| 3966 |
1/2✓ Branch 0 taken 23350 times.
✗ Branch 1 not taken.
|
23350 | mutex_exit(&undo::ddl_mutex); |
| 3967 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23350 times.
|
23350 | if (err != DB_SUCCESS) { |
| 3968 | ✗ | ib::error(ER_IB_MSG_FAILED_TO_FINISH_TRUNCATE, prefix.c_str(), | |
| 3969 | space_name); | ||
| 3970 | ✗ | continue; | |
| 3971 | } | ||
| 3972 | } | ||
| 3973 | |||
| 3974 | /* Check if IBD tablespaces exist in mem correctly. This call also adjusts | ||
| 3975 | the tablespace name for undo and general tablespace. We still need to check | ||
| 3976 | if the data files are moved. */ | ||
| 3977 |
3/4✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38434 times.
✓ Branch 3 taken 66184 times.
|
104618 | if (fil_space_exists_in_mem(space_id, space_name, false, true)) { |
| 3978 |
4/6✓ Branch 0 taken 38434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23335 times.
✓ Branch 3 taken 15099 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 38434 times.
|
61769 | if (fsp_is_undo_tablespace(space_id) && |
| 3979 |
2/4✓ Branch 0 taken 23335 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23335 times.
|
23335 | !apply_dd_undo_state(space_id, dd_tablespace)) { |
| 3980 | /* Undo tablespaces are always opened first. But in case they have | ||
| 3981 | been moved and the DD needs to be updated, we fall thru to the location | ||
| 3982 | check below. First though, update the DD tablespace state. */ | ||
| 3983 | ✗ | ib::warn(ER_IB_MSG_FAIL_TO_SAVE_SPACE_STATE, prefix.c_str(), | |
| 3984 | space_name); | ||
| 3985 | } | ||
| 3986 | } | ||
| 3987 | |||
| 3988 | /* Check the file paths of IBD and Undo datafiles below. */ | ||
| 3989 |
6/10✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23350 times.
✓ Branch 3 taken 81268 times.
✓ Branch 4 taken 23350 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 23350 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 104618 times.
|
104618 | if (!fsp_is_ibd_tablespace(space_id) && !fsp_is_undo_tablespace(space_id)) { |
| 3990 | ✗ | continue; | |
| 3991 | } | ||
| 3992 | |||
| 3993 | /* Check if any IBD or Undo files are moved, deleted or missing. */ | ||
| 3994 | 104618 | std::string new_path; | |
| 3995 | |||
| 3996 | /* Just in case this dictionary was ported between | ||
| 3997 | Windows and POSIX. */ | ||
| 3998 | 104618 | Fil_path::normalize(dd_path); | |
| 3999 | 104618 | Fil_state state = Fil_state::MATCHES; | |
| 4000 | |||
| 4001 | 104618 | uint32_t fsp_flags = 0; | |
| 4002 |
3/6✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 104618 times.
|
104618 | if (p.get(se_key_value[DD_SPACE_FLAGS], &fsp_flags)) { |
| 4003 | /* Failed to fetch the tablespace flags. */ | ||
| 4004 | ✗ | ++m_n_errors; | |
| 4005 | ✗ | break; | |
| 4006 | } | ||
| 4007 | |||
| 4008 |
1/2✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
|
104618 | std::lock_guard<std::mutex> guard(m_mutex); |
| 4009 | |||
| 4010 |
2/4✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104618 times.
✗ Branch 3 not taken.
|
104618 | state = fil_tablespace_path_equals(space_id, space_name, fsp_flags, dd_path, |
| 4011 | &new_path); | ||
| 4012 | |||
| 4013 |
2/2✓ Branch 0 taken 104316 times.
✓ Branch 1 taken 302 times.
|
104618 | if (state == Fil_state::MATCHES) { |
| 4014 |
1/2✓ Branch 0 taken 104316 times.
✗ Branch 1 not taken.
|
104316 | new_path.assign(dd_path); |
| 4015 | } | ||
| 4016 | |||
| 4017 |
1/2✓ Branch 0 taken 104618 times.
✗ Branch 1 not taken.
|
104618 | std::string space_str(space_name); |
| 4018 | |||
| 4019 | 104618 | std::string old_space; | |
| 4020 | 104618 | bool file_name_changed = false; | |
| 4021 | 104618 | bool file_path_changed = (state == Fil_state::MOVED); | |
| 4022 | |||
| 4023 |
4/4✓ Branch 0 taken 302 times.
✓ Branch 1 taken 104316 times.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 219 times.
|
104618 | if (state == Fil_state::MATCHES || state == Fil_state::MOVED) { |
| 4024 | /* We need to update space name and table name for partitioned tables | ||
| 4025 | if letter case is different. */ | ||
| 4026 |
3/4✓ Branch 0 taken 104399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 104298 times.
|
104399 | if (fil_update_partition_name(space_id, fsp_flags, true, space_str, |
| 4027 | new_path)) { | ||
| 4028 | 101 | file_name_changed = true; | |
| 4029 | 101 | state = Fil_state::MOVED; | |
| 4030 | } | ||
| 4031 | |||
| 4032 | /* Update DD if tablespace name is corrected. */ | ||
| 4033 |
2/2✓ Branch 0 taken 145 times.
✓ Branch 1 taken 104254 times.
|
104399 | if (space_str.compare(space_name) != 0) { |
| 4034 |
1/2✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
|
145 | old_space.assign(space_name); |
| 4035 | 145 | space_name = space_str.c_str(); | |
| 4036 | 145 | state = Fil_state::MOVED; | |
| 4037 | } | ||
| 4038 | } | ||
| 4039 | |||
| 4040 |
3/6✓ Branch 0 taken 104189 times.
✓ Branch 1 taken 219 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 210 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
104618 | switch (state) { |
| 4041 | 104189 | case Fil_state::MATCHES: | |
| 4042 | 104189 | break; | |
| 4043 | |||
| 4044 | 219 | case Fil_state::MISSING: | |
| 4045 | |||
| 4046 |
5/10✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 219 times.
✗ Branch 9 not taken.
|
438 | ib::warn(ER_IB_MSG_526) << prefix << "Tablespace " << space_id << "," |
| 4047 |
3/6✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
|
219 | << " name '" << space_name << "'," |
| 4048 |
3/6✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 219 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 219 times.
✗ Branch 5 not taken.
|
219 | << " file '" << dd_path << "'" |
| 4049 |
1/2✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
|
219 | << " is missing!"; |
| 4050 | |||
| 4051 |
3/4✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 217 times.
|
219 | if (fsp_is_undo_tablespace(space_id)) { |
| 4052 | /* This deserves a special error message. */ | ||
| 4053 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename); |
| 4054 | } | ||
| 4055 | 219 | ++m_n_missing; | |
| 4056 | 219 | continue; | |
| 4057 | |||
| 4058 | ✗ | case Fil_state::DELETED: | |
| 4059 | |||
| 4060 | ✗ | ib::warn(ER_IB_MSG_527) << prefix << "Tablespace " << space_id << "," | |
| 4061 | ✗ | << " name '" << space_name << "'," | |
| 4062 | ✗ | << " file '" << dd_path << "'" | |
| 4063 | ✗ | << " was deleted!"; | |
| 4064 | ✗ | ++m_n_deleted; | |
| 4065 | ✗ | continue; | |
| 4066 | |||
| 4067 | 210 | case Fil_state::MOVED: | |
| 4068 |
2/4✓ Branch 0 taken 210 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 210 times.
✗ Branch 3 not taken.
|
210 | fil_add_moved_space(dd_tablespace->id(), space_id, space_name, dd_path, |
| 4069 | new_path); | ||
| 4070 | 210 | ++m_n_moved; | |
| 4071 | |||
| 4072 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 210 times.
|
210 | if (m_n_moved > MOVED_FILES_PRINT_THRESHOLD) { |
| 4073 | ✗ | filename = new_path.c_str(); | |
| 4074 | |||
| 4075 | ✗ | break; | |
| 4076 | } | ||
| 4077 | |||
| 4078 |
2/2✓ Branch 0 taken 145 times.
✓ Branch 1 taken 65 times.
|
210 | if (!old_space.empty()) { |
| 4079 |
1/2✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
|
145 | ib::info(ER_IB_MSG_FIL_STATE_MOVED_CORRECTED, prefix.c_str(), |
| 4080 | 145 | static_cast<unsigned long long>(dd_tablespace->id()), | |
| 4081 |
1/2✓ Branch 0 taken 145 times.
✗ Branch 1 not taken.
|
290 | static_cast<unsigned int>(space_id), old_space.c_str(), |
| 4082 | space_name); | ||
| 4083 | } | ||
| 4084 | |||
| 4085 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 127 times.
|
210 | if (file_path_changed) { |
| 4086 |
1/2✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
|
83 | ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_PATH, prefix.c_str(), |
| 4087 | 83 | static_cast<unsigned long long>(dd_tablespace->id()), | |
| 4088 | ✗ | static_cast<unsigned int>(space_id), space_name, | |
| 4089 |
1/2✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
|
166 | dd_path.c_str(), new_path.c_str()); |
| 4090 | |||
| 4091 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 26 times.
|
127 | } else if (file_name_changed) { |
| 4092 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
101 | ib::info(ER_IB_MSG_FIL_STATE_MOVED_CHANGED_NAME, prefix.c_str(), |
| 4093 | 101 | static_cast<unsigned long long>(dd_tablespace->id()), | |
| 4094 | ✗ | static_cast<unsigned int>(space_id), space_name, | |
| 4095 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
202 | dd_path.c_str(), new_path.c_str()); |
| 4096 | } | ||
| 4097 | |||
| 4098 | 210 | filename = new_path.c_str(); | |
| 4099 | |||
| 4100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 210 times.
|
210 | if (m_n_moved == MOVED_FILES_PRINT_THRESHOLD) { |
| 4101 | ✗ | ib::info(ER_IB_MSG_FIL_STATE_MOVED_TOO_MANY, prefix.c_str()); | |
| 4102 | } | ||
| 4103 | 210 | break; | |
| 4104 | |||
| 4105 | ✗ | case Fil_state::RENAMED: | |
| 4106 | ✗ | break; | |
| 4107 | } | ||
| 4108 | |||
| 4109 | /* If this space is already open, we can move on to the next. */ | ||
| 4110 |
3/4✓ Branch 0 taken 104399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38450 times.
✓ Branch 3 taken 65949 times.
|
104399 | if (nullptr != fil_space_get(space_id)) { |
| 4111 | /* Set the autoextend_size attribute for the newly opened space. */ | ||
| 4112 | 38450 | uint64_t autoextend_size{}; | |
| 4113 | |||
| 4114 |
6/10✓ Branch 0 taken 38450 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38450 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26519 times.
✓ Branch 5 taken 11931 times.
✓ Branch 6 taken 26519 times.
✓ Branch 7 taken 11931 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
103419 | if (o.exists(autoextend_size_str) && |
| 4115 |
6/12✓ Branch 0 taken 26519 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26519 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26519 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 26519 times.
✓ Branch 7 taken 11931 times.
✓ Branch 8 taken 38450 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
64969 | !o.get(autoextend_size_str, &autoextend_size)) { |
| 4116 |
1/2✓ Branch 0 taken 26519 times.
✗ Branch 1 not taken.
|
26519 | ut_d(dberr_t ret =) fil_set_autoextend_size(space_id, autoextend_size); |
| 4117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26519 times.
|
26519 | ut_ad(ret == DB_SUCCESS); |
| 4118 | } | ||
| 4119 | 38450 | ++m_n_validated; | |
| 4120 | 38450 | continue; | |
| 4121 | 38450 | } | |
| 4122 | |||
| 4123 |
3/4✓ Branch 0 taken 65949 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 65936 times.
|
65949 | if (fsp_is_undo_tablespace(space_id)) { |
| 4124 | /* The undo space may be open with a alternate space_id */ | ||
| 4125 | 13 | space_id_t space_num = undo::id2num(space_id); | |
| 4126 |
3/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1 times.
|
13 | if (nullptr != undo::spaces->find(space_num)) { |
| 4127 | 12 | ++m_n_validated; | |
| 4128 | 12 | continue; | |
| 4129 | } | ||
| 4130 | |||
| 4131 | /* If an undo tablespace from the DD is in an unknown location, | ||
| 4132 | it will not yet be open. */ | ||
| 4133 | 1 | undo::Tablespace undo_space(space_id); | |
| 4134 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo_space.set_space_name(space_name); |
| 4135 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo_space.set_file_name(filename); |
| 4136 | |||
| 4137 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | mutex_enter(&undo::ddl_mutex); |
| 4138 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo::spaces->x_lock(); |
| 4139 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo::use_space_id(space_id); |
| 4140 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dberr_t err = srv_undo_tablespace_open(undo_space); |
| 4141 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | undo::spaces->x_unlock(); |
| 4142 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | mutex_exit(&undo::ddl_mutex); |
| 4143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err != DB_SUCCESS) { |
| 4144 | ✗ | ib::error(ER_IB_MSG_CANNOT_FIND_DD_UNDO_SPACE, space_name, filename); | |
| 4145 | } | ||
| 4146 | 1 | ++m_n_validated; | |
| 4147 | 1 | continue; | |
| 4148 | 1 | } | |
| 4149 | |||
| 4150 | 65936 | Keyring_encryption_info keyring_encryption_info; | |
| 4151 | |||
| 4152 | /* It's safe to pass space_name in tablename charset because | ||
| 4153 | filename is already in filename charset. */ | ||
| 4154 |
4/4✓ Branch 0 taken 12145 times.
✓ Branch 1 taken 53791 times.
✓ Branch 2 taken 12133 times.
✓ Branch 3 taken 12 times.
|
65936 | bool validate = recv_needed_recovery && srv_force_recovery == 0; |
| 4155 |
1/2✓ Branch 0 taken 65936 times.
✗ Branch 1 not taken.
|
65936 | dberr_t err = fil_ibd_open( |
| 4156 |
3/4✓ Branch 0 taken 53803 times.
✓ Branch 1 taken 12133 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53803 times.
|
65936 | validate || is_enc_in_progress, FIL_TYPE_TABLESPACE, space_id, fsp_flags, |
| 4157 | space_name, filename, false, false, keyring_encryption_info); | ||
| 4158 | |||
| 4159 |
2/2✓ Branch 0 taken 65667 times.
✓ Branch 1 taken 269 times.
|
65936 | switch (err) { |
| 4160 | 65667 | case DB_SUCCESS: { | |
| 4161 | /* Set the autoextend_size attribute for the newly opened space. */ | ||
| 4162 | 65667 | uint64_t autoextend_size{}; | |
| 4163 | |||
| 4164 |
6/10✓ Branch 0 taken 65667 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65667 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 64811 times.
✓ Branch 5 taken 856 times.
✓ Branch 6 taken 64811 times.
✓ Branch 7 taken 856 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
196145 | if (o.exists(autoextend_size_str) && |
| 4165 |
6/12✓ Branch 0 taken 64811 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 64811 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 64811 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 64811 times.
✓ Branch 7 taken 856 times.
✓ Branch 8 taken 65667 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
130478 | !o.get(autoextend_size_str, &autoextend_size)) { |
| 4166 | ut_d(dberr_t ret =) | ||
| 4167 |
1/2✓ Branch 0 taken 64811 times.
✗ Branch 1 not taken.
|
64811 | fil_set_autoextend_size(space_id, autoextend_size); |
| 4168 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64811 times.
|
64811 | ut_ad(ret == DB_SUCCESS); |
| 4169 | } | ||
| 4170 | 65667 | ++m_n_validated; | |
| 4171 | 65667 | break; | |
| 4172 | } | ||
| 4173 | 269 | case DB_CANNOT_OPEN_FILE: | |
| 4174 | case DB_WRONG_FILE_NAME: | ||
| 4175 | default: | ||
| 4176 |
5/10✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 269 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 269 times.
✗ Branch 9 not taken.
|
269 | ib::info(ER_IB_MSG_530) << prefix << "Tablespace " << space_id << "," |
| 4177 |
3/6✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
|
269 | << " name '" << space_name << "'," |
| 4178 |
1/2✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
|
269 | << " unable to open file" |
| 4179 |
5/10✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 269 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 269 times.
✗ Branch 9 not taken.
|
269 | << " '" << filename << "' - " << ut_strerr(err); |
| 4180 | 269 | ++m_n_missing; | |
| 4181 | } | ||
| 4182 |
10/12✓ Branch 0 taken 65936 times.
✓ Branch 1 taken 38682 times.
✓ Branch 2 taken 65936 times.
✓ Branch 3 taken 38682 times.
✓ Branch 4 taken 65936 times.
✓ Branch 5 taken 38682 times.
✓ Branch 6 taken 65936 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 38682 times.
✓ Branch 9 taken 65936 times.
✓ Branch 10 taken 38682 times.
✗ Branch 11 not taken.
|
259346 | } |
| 4183 | |||
| 4184 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | mem_heap_free(heap); |
| 4185 | 11531 | } | |
| 4186 | |||
| 4187 | 11531 | dberr_t Validate_files::validate(const DD_tablespaces &tablespaces) { | |
| 4188 | 11531 | m_n_to_check = tablespaces.size(); | |
| 4189 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | m_n_threads = fil_get_scan_threads(m_n_to_check); |
| 4190 | 11531 | m_start_time = std::chrono::steady_clock::now(); | |
| 4191 | |||
| 4192 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 11517 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 3 times.
|
11531 | if (!srv_validate_tablespace_paths && !recv_needed_recovery) { |
| 4193 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | ib::info(ER_IB_TABLESPACE_PATH_VALIDATION_SKIPPED); |
| 4194 | } | ||
| 4195 | |||
| 4196 | using std::placeholders::_1; | ||
| 4197 | using std::placeholders::_2; | ||
| 4198 | using std::placeholders::_3; | ||
| 4199 | |||
| 4200 | std::function<void(const Validate_files::Const_iter &, | ||
| 4201 | const Validate_files::Const_iter &, size_t)> | ||
| 4202 |
2/4✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
|
11531 | check = std::bind(&Validate_files::check, this, _1, _2, _3); |
| 4203 | |||
| 4204 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | par_for(PFS_NOT_INSTRUMENTED, tablespaces, m_n_threads, check); |
| 4205 | |||
| 4206 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | std::ostringstream msg; |
| 4207 |
2/4✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
|
11531 | msg << "Scanned " << m_n_to_check << " tablespaces." |
| 4208 |
4/8✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11531 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11531 times.
✗ Branch 7 not taken.
|
23062 | << " Validated " << m_n_validated.load() << "."; |
| 4209 | |||
| 4210 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 11487 times.
|
23062 | if (m_n_skipped.load() > 0) { |
| 4211 |
3/6✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
|
88 | msg << " Skipped " << m_n_skipped.load() << "."; |
| 4212 | } | ||
| 4213 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 11507 times.
|
23062 | if (m_n_moved.load() > 0) { |
| 4214 |
3/6✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
|
48 | msg << " Found " << m_n_moved.load() << " moved."; |
| 4215 | } | ||
| 4216 |
2/2✓ Branch 0 taken 217 times.
✓ Branch 1 taken 11314 times.
|
23062 | if (m_n_missing.load() > 0) { |
| 4217 |
3/6✓ Branch 0 taken 217 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 217 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 217 times.
✗ Branch 5 not taken.
|
434 | msg << " Found " << m_n_missing.load() << " missing."; |
| 4218 | } | ||
| 4219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
|
23062 | if (m_n_deleted.load() > 0) { |
| 4220 | ✗ | msg << " Found " << m_n_deleted.load() << " deleted."; | |
| 4221 | } | ||
| 4222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
|
23062 | if (m_n_errors.load() > 0) { |
| 4223 | ✗ | msg << " Encountered " << m_n_errors.load() << " errors."; | |
| 4224 | } | ||
| 4225 |
3/6✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11531 times.
✗ Branch 5 not taken.
|
11531 | ib::info(ER_IB_MSG_531) << msg.str(); |
| 4226 | |||
| 4227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
|
11531 | if (failed()) { |
| 4228 | ✗ | return (DB_ERROR); | |
| 4229 | } | ||
| 4230 | |||
| 4231 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | fil_set_max_space_id_if_bigger(get_space_max_id()); |
| 4232 | |||
| 4233 |
2/2✓ Branch 0 taken 11517 times.
✓ Branch 1 taken 14 times.
|
11531 | if (srv_validate_tablespace_paths) { |
| 4234 | 11517 | clone_sys->set_space_initialized(); | |
| 4235 | } | ||
| 4236 | |||
| 4237 | 11531 | return (DB_SUCCESS); | |
| 4238 | 11531 | } | |
| 4239 | |||
| 4240 | /** Discover all InnoDB tablespaces. | ||
| 4241 | @param[in,out] thd thread handle | ||
| 4242 | @retval true on error | ||
| 4243 | @retval false on success */ | ||
| 4244 | 11531 | [[nodiscard]] static bool boot_tablespaces(THD *thd) { | |
| 4245 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | auto dc = dd::get_dd_client(thd); |
| 4246 | |||
| 4247 | using DD_tablespaces = std::vector<const dd::Tablespace *>; | ||
| 4248 | using Releaser = dd::cache::Dictionary_client::Auto_releaser; | ||
| 4249 | |||
| 4250 | 11531 | DD_tablespaces tablespaces; | |
| 4251 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | Releaser releaser(dc); |
| 4252 | |||
| 4253 | /* Initialize the max space_id from sys header */ | ||
| 4254 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | dict_sys_mutex_enter(); |
| 4255 | |||
| 4256 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | mtr_t mtr; |
| 4257 | |||
| 4258 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | mtr_start(&mtr); |
| 4259 | |||
| 4260 |
2/4✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
|
11531 | space_id_t space_max_id = mtr_read_ulint( |
| 4261 | dict_hdr_get(&mtr) + DICT_HDR_MAX_SPACE_ID, MLOG_4BYTES, &mtr); | ||
| 4262 | |||
| 4263 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | mtr_commit(&mtr); |
| 4264 | |||
| 4265 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | fil_set_max_space_id_if_bigger(space_max_id); |
| 4266 | |||
| 4267 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | dict_sys_mutex_exit(); |
| 4268 | |||
| 4269 |
2/4✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
|
11531 | ib::info(ER_IB_MSG_532) << "Reading DD tablespace files"; |
| 4270 | |||
| 4271 |
2/4✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11531 times.
|
11531 | if (dc->fetch_global_components(&tablespaces)) { |
| 4272 | /* Failed to fetch the tablespaces from the DD. */ | ||
| 4273 | |||
| 4274 | ✗ | return (DD_FAILURE); | |
| 4275 | } | ||
| 4276 | |||
| 4277 | 11531 | Validate_files validator; | |
| 4278 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | dberr_t err = validator.validate(tablespaces); |
| 4279 | |||
| 4280 |
1/2✓ Branch 0 taken 11531 times.
✗ Branch 1 not taken.
|
11531 | return (err == DB_SUCCESS ? DD_SUCCESS : DD_FAILURE); |
| 4281 | 11531 | } | |
| 4282 | |||
| 4283 | /** Create metadata for a predefined tablespace at server initialization. | ||
| 4284 | @param[in,out] dd_client data dictionary client | ||
| 4285 | @param[in] space_id InnoDB tablespace ID | ||
| 4286 | @param[in] flags tablespace flags | ||
| 4287 | @param[in] name tablespace name | ||
| 4288 | @param[in] filename tablespace file name | ||
| 4289 | @retval false on success | ||
| 4290 | @retval true on failure */ | ||
| 4291 | 1140 | static bool predefine_tablespace(dd::cache::Dictionary_client *dd_client, | |
| 4292 | space_id_t space_id, uint32_t flags, | ||
| 4293 | const char *name, const char *filename) { | ||
| 4294 | dd::Object_id dd_space_id; | ||
| 4295 | |||
| 4296 |
1/2✓ Branch 0 taken 1140 times.
✗ Branch 1 not taken.
|
1140 | return (dd_create_tablespace(dd_client, name, space_id, flags, filename, |
| 4297 | 2280 | false, dd_space_id)); | |
| 4298 | } | ||
| 4299 | |||
| 4300 | /** Check if InnoDB is in a mode where the data dictionary is read-only. | ||
| 4301 | @return true if srv_read_only_mode is true or if srv_force_recovery > 0 */ | ||
| 4302 | 93181 | static bool innobase_is_dict_readonly() { | |
| 4303 |
1/2✓ Branch 0 taken 93181 times.
✗ Branch 1 not taken.
|
93181 | DBUG_TRACE; |
| 4304 |
4/4✓ Branch 0 taken 92978 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 92898 times.
|
186362 | return srv_read_only_mode || srv_force_recovery > 0; |
| 4305 | 93181 | } | |
| 4306 | |||
| 4307 | #ifndef UNIV_HOTBACKUP | ||
| 4308 | /** Update metadata for innodb_temporary tablespace at server startup. | ||
| 4309 | This information is used by the information_schema.files to show the | ||
| 4310 | filename for the temporary tablespace innodb_temporary. | ||
| 4311 | @param[in,out] thd THD | ||
| 4312 | @retval false on success | ||
| 4313 | @retval true on failure */ | ||
| 4314 | 11911 | static bool update_innodb_temporary_metadata(THD *thd) { | |
| 4315 |
3/4✓ Branch 0 taken 11911 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 11853 times.
|
11911 | if (innobase_is_dict_readonly()) { |
| 4316 | /* Metadata cannot be updated if the server is started in read_only | ||
| 4317 | mode. This means that the values for innodb_temp_data_file_path and | ||
| 4318 | file_name in information_schema.files will not be in same. */ | ||
| 4319 |
8/16✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 58 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 58 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 58 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 58 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 58 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 58 times.
✗ Branch 15 not taken.
|
58 | LogErr(WARNING_LEVEL, ER_SKIP_UPDATING_METADATA_IN_SE_RO_MODE, |
| 4320 | "information_schema"); | ||
| 4321 | 58 | return false; | |
| 4322 | } | ||
| 4323 | |||
| 4324 | /* Get the filename from srv_tmp_space */ | ||
| 4325 |
1/2✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
|
11853 | auto fpath = srv_tmp_space.first_datafile()->filepath(); |
| 4326 | 11853 | auto &dc = *thd->dd_client(); | |
| 4327 |
1/2✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
|
11853 | dd::cache::Dictionary_client::Auto_releaser releaser(&dc); |
| 4328 |
1/2✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
|
11853 | const dd::String_type tbsp_name{dict_sys_t::s_temp_space_name}; |
| 4329 | 11853 | dd::Tablespace *tmp_tbsp{nullptr}; | |
| 4330 | |||
| 4331 |
3/6✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11853 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11853 times.
✗ Branch 5 not taken.
|
23706 | if (!dc.acquire_for_modification<dd::Tablespace>(tbsp_name, &tmp_tbsp) && |
| 4332 |
1/2✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
|
11853 | tmp_tbsp != nullptr) { |
| 4333 |
2/4✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11853 times.
|
11853 | ut_ad(tmp_tbsp->files().size() == 1); |
| 4334 | |||
| 4335 | /* Get the tablespace file for innodb_temporary tablespace. */ | ||
| 4336 | dd::Tablespace_file *dd_file = | ||
| 4337 |
3/6✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11853 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11853 times.
✗ Branch 5 not taken.
|
11853 | const_cast<dd::Tablespace_file *>(*(tmp_tbsp->files().begin())); |
| 4338 | |||
| 4339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11853 times.
|
11853 | ut_ad(dd_file); |
| 4340 | |||
| 4341 |
2/4✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11853 times.
✗ Branch 3 not taken.
|
11853 | dd_file->set_filename(fpath); |
| 4342 | |||
| 4343 |
2/4✓ Branch 0 taken 11853 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11853 times.
|
11853 | if (dc.update(tmp_tbsp)) { |
| 4344 | /* Unable to update the metadata. */ | ||
| 4345 | ✗ | ut_d(ut_error); | |
| 4346 | ut_o(return true); | ||
| 4347 | } | ||
| 4348 | } else { | ||
| 4349 | /* Unable to acquire innodb_temporary tablespace for modification. */ | ||
| 4350 | ✗ | ut_d(ut_error); | |
| 4351 | ut_o(return true); | ||
| 4352 | } | ||
| 4353 | 11853 | return false; | |
| 4354 | 11853 | } | |
| 4355 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4356 | |||
| 4357 | /** Predefine the undo tablespace metadata at server initialization. | ||
| 4358 | @param[in,out] dd_client data dictionary client | ||
| 4359 | @retval false on success | ||
| 4360 | @retval true on failure */ | ||
| 4361 | 380 | static bool predefine_undo_tablespaces( | |
| 4362 | dd::cache::Dictionary_client *dd_client) { | ||
| 4363 | /** Undo tablespaces use a reserved range of tablespace ID. */ | ||
| 4364 |
2/2✓ Branch 0 taken 760 times.
✓ Branch 1 taken 380 times.
|
1140 | for (auto undo_space : undo::spaces->m_spaces) { |
| 4365 |
1/2✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
|
760 | uint32_t flags = fsp_flags_init(univ_page_size, false, false, false, false); |
| 4366 | |||
| 4367 |
2/4✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 760 times.
|
760 | if (predefine_tablespace(dd_client, undo_space->id(), flags, |
| 4368 | 760 | undo_space->space_name(), | |
| 4369 |
2/4✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 760 times.
✗ Branch 3 not taken.
|
760 | undo_space->file_name())) { |
| 4370 | ✗ | return (true); | |
| 4371 | } | ||
| 4372 | } | ||
| 4373 | |||
| 4374 | 380 | return (false); | |
| 4375 | } | ||
| 4376 | |||
| 4377 | /** Invalidate an entry or entries for partitoined table from the dict cache. | ||
| 4378 | @param[in] schema_name Schema name | ||
| 4379 | @param[in] table_name Table name */ | ||
| 4380 | 341864 | static void innobase_dict_cache_reset(const char *schema_name, | |
| 4381 | const char *table_name) { | ||
| 4382 | char name[FN_REFLEN]; | ||
| 4383 | 341864 | snprintf(name, sizeof name, "%s/%s", schema_name, table_name); | |
| 4384 | |||
| 4385 |
1/2✓ Branch 0 taken 341864 times.
✗ Branch 1 not taken.
|
341864 | dict_sys_mutex_enter(); |
| 4386 | |||
| 4387 |
1/2✓ Branch 0 taken 341864 times.
✗ Branch 1 not taken.
|
341864 | dict_table_t *table = dict_table_check_if_in_cache_low(name); |
| 4388 | |||
| 4389 |
2/2✓ Branch 0 taken 200762 times.
✓ Branch 1 taken 141102 times.
|
341864 | if (table != nullptr) { |
| 4390 |
1/2✓ Branch 0 taken 200762 times.
✗ Branch 1 not taken.
|
200762 | btr_drop_ahi_for_table(table); |
| 4391 |
1/2✓ Branch 0 taken 200762 times.
✗ Branch 1 not taken.
|
200762 | dict_table_remove_from_cache(table); |
| 4392 |
2/2✓ Branch 0 taken 2384 times.
✓ Branch 1 taken 138718 times.
|
141102 | } else if (strcmp(schema_name, "mysql") != 0) { |
| 4393 |
1/2✓ Branch 0 taken 2384 times.
✗ Branch 1 not taken.
|
2384 | dict_partitioned_table_remove_from_cache(name); |
| 4394 | } | ||
| 4395 | |||
| 4396 |
1/2✓ Branch 0 taken 341864 times.
✗ Branch 1 not taken.
|
341864 | dict_sys_mutex_exit(); |
| 4397 | 341864 | } | |
| 4398 | |||
| 4399 | /** Invalidate user table dict cache after Replication Plugin recovers. Table | ||
| 4400 | definition could be different with XA commit/rollback of DDL operations */ | ||
| 4401 | 11787 | static void innobase_dict_cache_reset_tables_and_tablespaces() { | |
| 4402 | 11787 | dict_sys_mutex_enter(); | |
| 4403 | |||
| 4404 | /* There should be no DDL/DML activity at this stage, so access | ||
| 4405 | the LRU chain without mutex. We only invalidates the table | ||
| 4406 | in LRU list */ | ||
| 4407 |
7/12✓ Branch 0 taken 11787 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11787 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11787 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 130518 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 142305 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 130518 times.
✓ Branch 11 taken 11787 times.
|
142305 | for (auto table : dict_sys->table_LRU.removable()) { |
| 4408 | /* Make sure table->is_dd_table is set */ | ||
| 4409 | |||
| 4410 | 130518 | std::string db_str; | |
| 4411 | 130518 | std::string tbl_str; | |
| 4412 |
2/4✓ Branch 0 taken 130518 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 130518 times.
✗ Branch 3 not taken.
|
130518 | dict_name::get_table(table->name.m_name, db_str, tbl_str); |
| 4413 | |||
| 4414 | /* TODO: Remove follow if we have better way to identify | ||
| 4415 | DD "system table" */ | ||
| 4416 |
1/2✓ Branch 0 taken 7026 times.
✗ Branch 1 not taken.
|
137544 | if (db_str.compare("mysql") == 0 || table->is_dd_table || |
| 4417 |
9/10✓ Branch 0 taken 7026 times.
✓ Branch 1 taken 123492 times.
✓ Branch 2 taken 7026 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7025 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1501 times.
✓ Branch 7 taken 5524 times.
✓ Branch 8 taken 124994 times.
✓ Branch 9 taken 5524 times.
|
144569 | table->is_corrupted() || |
| 4418 | 7025 | DICT_TF2_FLAG_IS_SET(table, DICT_TF2_RESURRECT_PREPARED)) { | |
| 4419 | 124994 | continue; | |
| 4420 | } | ||
| 4421 | |||
| 4422 |
1/2✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
|
5524 | table->acquire(); |
| 4423 |
1/2✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
|
5524 | btr_drop_ahi_for_table(table); |
| 4424 |
1/2✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
|
5524 | dd_table_close(table, nullptr, nullptr, true); |
| 4425 | |||
| 4426 |
1/2✓ Branch 0 taken 5524 times.
✗ Branch 1 not taken.
|
5524 | dict_table_remove_from_cache(table); |
| 4427 |
4/4✓ Branch 0 taken 5524 times.
✓ Branch 1 taken 124994 times.
✓ Branch 2 taken 5524 times.
✓ Branch 3 taken 124994 times.
|
255512 | } |
| 4428 | 11787 | dict_sys_mutex_exit(); | |
| 4429 | 11787 | } | |
| 4430 | |||
| 4431 | /** Perform high-level recovery in InnoDB as part of initializing the | ||
| 4432 | data dictionary. | ||
| 4433 | @param[in] dict_recovery_mode How to do recovery | ||
| 4434 | @param[in] version Target DD version if a new | ||
| 4435 | server is being installed. | ||
| 4436 | Actual DD version if restarting | ||
| 4437 | an existing server. | ||
| 4438 | @retval true An error occurred. | ||
| 4439 | @retval false Success - no errors. */ | ||
| 4440 | 12291 | static bool innobase_dict_recover(dict_recovery_mode_t dict_recovery_mode, | |
| 4441 | uint version [[maybe_unused]]) { | ||
| 4442 | 12291 | THD *thd = current_thd; | |
| 4443 | |||
| 4444 |
2/3✓ Branch 0 taken 380 times.
✓ Branch 1 taken 11911 times.
✗ Branch 2 not taken.
|
12291 | switch (dict_recovery_mode) { |
| 4445 | 380 | case DICT_RECOVERY_INITIALIZE_TABLESPACES: | |
| 4446 | 380 | break; | |
| 4447 | 11911 | case DICT_RECOVERY_RESTART_SERVER: | |
| 4448 | [[fallthrough]]; | ||
| 4449 | case DICT_RECOVERY_INITIALIZE_SERVER: | ||
| 4450 |
2/2✓ Branch 0 taken 10301 times.
✓ Branch 1 taken 1610 times.
|
11911 | if (dict_sys->dynamic_metadata == nullptr) { |
| 4451 | 20602 | dict_sys->dynamic_metadata = | |
| 4452 | 10301 | dd_table_open_on_name(thd, nullptr, "mysql/innodb_dynamic_metadata", | |
| 4453 | false, DICT_ERR_IGNORE_NONE); | ||
| 4454 | 20602 | dict_persist->table_buffer = | |
| 4455 | 10301 | ut::new_withkey<DDTableBuffer>(UT_NEW_THIS_FILE_PSI_KEY); | |
| 4456 | } | ||
| 4457 | |||
| 4458 | 23822 | dict_sys->table_stats = | |
| 4459 | 11911 | dd_table_open_on_name(thd, nullptr, "mysql/innodb_table_stats", false, | |
| 4460 | DICT_ERR_IGNORE_NONE); | ||
| 4461 | 23822 | dict_sys->index_stats = | |
| 4462 | 11911 | dd_table_open_on_name(thd, nullptr, "mysql/innodb_index_stats", false, | |
| 4463 | DICT_ERR_IGNORE_NONE); | ||
| 4464 | 11911 | dict_sys->ddl_log = dd_table_open_on_name( | |
| 4465 | thd, nullptr, "mysql/innodb_ddl_log", false, DICT_ERR_IGNORE_NONE); | ||
| 4466 | 11911 | log_ddl = ut::new_withkey<Log_DDL>(UT_NEW_THIS_FILE_PSI_KEY); | |
| 4467 | } | ||
| 4468 | |||
| 4469 |
3/4✓ Branch 0 taken 380 times.
✓ Branch 1 taken 380 times.
✓ Branch 2 taken 11531 times.
✗ Branch 3 not taken.
|
12291 | switch (dict_recovery_mode) { |
| 4470 | 380 | case DICT_RECOVERY_INITIALIZE_SERVER: | |
| 4471 | 380 | return (false); | |
| 4472 | 380 | case DICT_RECOVERY_INITIALIZE_TABLESPACES: { | |
| 4473 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 4474 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 4475 | |||
| 4476 |
2/4✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
|
380 | if (predefine_tablespace(client, dict_sys_t::s_temp_space_id, |
| 4477 | srv_tmp_space.flags(), | ||
| 4478 | dict_sys_t::s_temp_space_name, | ||
| 4479 | dict_sys_t::s_temp_space_file_name)) { | ||
| 4480 | ✗ | return (DD_FAILURE); | |
| 4481 | } | ||
| 4482 | |||
| 4483 |
2/4✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 380 times.
|
380 | if (predefine_undo_tablespaces(client)) { |
| 4484 | ✗ | return (DD_FAILURE); | |
| 4485 | } | ||
| 4486 | |||
| 4487 | 380 | break; | |
| 4488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
|
380 | } |
| 4489 | 11531 | case DICT_RECOVERY_RESTART_SERVER: | |
| 4490 | /* Traverse dd::tablespaces and apply/validate this metadata. */ | ||
| 4491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
|
11531 | if (boot_tablespaces(thd)) { |
| 4492 | ✗ | return (true); | |
| 4493 | } | ||
| 4494 | |||
| 4495 | #ifndef UNIV_HOTBACKUP | ||
| 4496 | /* For all tablespaces for which tablespace key is to be reencrypt, | ||
| 4497 | do it now. */ | ||
| 4498 | 11531 | fil_encryption_reencrypt(Encryption::s_tablespaces_to_reencrypt); | |
| 4499 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4500 | |||
| 4501 | /* We might need to fix tables for CSV and MyISAM SE */ | ||
| 4502 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11531 times.
|
11531 | if (fix_cloned_tables(thd)) { |
| 4503 | ✗ | return (true); | |
| 4504 | } | ||
| 4505 | |||
| 4506 | 11531 | srv_dict_recover_on_restart(); | |
| 4507 | } | ||
| 4508 | |||
| 4509 | 11911 | srv_start_threads(dict_recovery_mode != DICT_RECOVERY_RESTART_SERVER); | |
| 4510 | |||
| 4511 | #ifndef UNIV_HOTBACKUP | ||
| 4512 | /* Update the metadata for innodb_temporary tablespace to reflect | ||
| 4513 | the correct filename. */ | ||
| 4514 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11911 times.
|
11911 | if (update_innodb_temporary_metadata(thd)) { |
| 4515 | ✗ | return true; | |
| 4516 | } | ||
| 4517 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4518 | |||
| 4519 | 11911 | return (fil_open_for_business(srv_read_only_mode) != DB_SUCCESS); | |
| 4520 | } | ||
| 4521 | |||
| 4522 | /** DDL crash recovery: process the records recovered from "log_ddl" table */ | ||
| 4523 | 11787 | static void innobase_post_recover() { | |
| 4524 |
2/2✓ Branch 0 taken 11771 times.
✓ Branch 1 taken 16 times.
|
11787 | if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { |
| 4525 |
2/4✓ Branch 0 taken 11771 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11771 times.
|
11771 | DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_2", |
| 4526 | srv_inject_too_many_concurrent_trxs = true;); | ||
| 4527 | |||
| 4528 |
1/2✓ Branch 0 taken 11771 times.
✗ Branch 1 not taken.
|
11771 | dberr_t err = log_ddl->recover(); |
| 4529 | |||
| 4530 | /* Abort post recovery startup if this is not successful. */ | ||
| 4531 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11771 times.
|
11771 | if (err != DB_SUCCESS) { |
| 4532 | ✗ | ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_POST_RECOVER_DDL_LOG_RECOVER); | |
| 4533 | } | ||
| 4534 | } | ||
| 4535 | |||
| 4536 |
1/2✓ Branch 0 taken 11787 times.
✗ Branch 1 not taken.
|
11787 | fil_free_scanned_files(); |
| 4537 | |||
| 4538 | /* If undo tablespaces are to be encrypted, encrypt them now */ | ||
| 4539 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 11759 times.
|
11787 | if (srv_undo_log_encrypt) { |
| 4540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | ut_ad(Encryption::check_keyring()); |
| 4541 | |||
| 4542 | /* There would be at least 2 UNDO tablespaces */ | ||
| 4543 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES); |
| 4544 | |||
| 4545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
28 | if (srv_read_only_mode) { |
| 4546 | ✗ | ib::error(ER_IB_MSG_1051); | |
| 4547 | ✗ | srv_undo_log_encrypt = false; | |
| 4548 | } else { | ||
| 4549 | /* Enable encryption for UNDO tablespaces */ | ||
| 4550 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | mutex_enter(&undo::ddl_mutex); |
| 4551 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
|
28 | if (srv_enable_undo_encryption(nullptr)) { |
| 4552 | ✗ | srv_undo_log_encrypt = false; | |
| 4553 | ✗ | ut_d(ut_error); | |
| 4554 | } | ||
| 4555 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | mutex_exit(&undo::ddl_mutex); |
| 4556 | |||
| 4557 | /* We have to ensure that the first page of the undo tablespaces gets | ||
| 4558 | flushed to disk. Otherwise during recovery, since we read the first | ||
| 4559 | page without applying the redo logs, it will be determined that | ||
| 4560 | encryption is off. */ | ||
| 4561 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | buf_flush_sync_all_buf_pools(); |
| 4562 | } | ||
| 4563 | } | ||
| 4564 | |||
| 4565 | /* If redo log is to be encrypted, encrypt it now */ | ||
| 4566 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 11755 times.
|
11787 | if (srv_redo_log_encrypt) { |
| 4567 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | ut_ad(Encryption::check_keyring()); |
| 4568 | |||
| 4569 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (srv_read_only_mode) { |
| 4570 | ✗ | ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY); | |
| 4571 | ✗ | srv_redo_log_encrypt = false; | |
| 4572 | } else { | ||
| 4573 | /* Enable encryption for REDO log */ | ||
| 4574 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
32 | if (srv_enable_redo_encryption()) { |
| 4575 | ✗ | srv_redo_log_encrypt = false; | |
| 4576 | ✗ | ut_d(ut_error); | |
| 4577 | } | ||
| 4578 | } | ||
| 4579 | } | ||
| 4580 | |||
| 4581 |
4/4✓ Branch 0 taken 11747 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 11737 times.
|
11787 | if (srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) { |
| 4582 | 50 | purge_sys->state = PURGE_STATE_DISABLED; | |
| 4583 | 50 | return; | |
| 4584 | } | ||
| 4585 | |||
| 4586 |
1/2✓ Branch 0 taken 11737 times.
✗ Branch 1 not taken.
|
11737 | Auto_THD thd; |
| 4587 |
2/4✓ Branch 0 taken 11737 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11737 times.
|
11737 | if (dd_tablespace_update_cache(thd.thd)) { |
| 4588 | ✗ | ut_d(ut_error); | |
| 4589 | } | ||
| 4590 | |||
| 4591 |
1/2✓ Branch 0 taken 11735 times.
✗ Branch 1 not taken.
|
11737 | srv_start_threads_after_ddl_recovery(); |
| 4592 | |||
| 4593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11735 times.
|
11735 | ut_a(innodb_inited); |
| 4594 | |||
| 4595 |
2/2✓ Branch 0 taken 11445 times.
✓ Branch 1 taken 290 times.
|
11735 | if (!opt_initialize) { |
| 4596 |
2/4✓ Branch 0 taken 11438 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11438 times.
|
11445 | if (!log_pfs_create_tables()) { |
| 4597 | ✗ | ib::warn(ER_IB_MSG_LOG_PFS_CREATE_TABLES_FAILED); | |
| 4598 | } | ||
| 4599 | } | ||
| 4600 | 11728 | } | |
| 4601 | |||
| 4602 | /** | ||
| 4603 | Get the server version id stored in the header of the | ||
| 4604 | dictionary tablespace. | ||
| 4605 | |||
| 4606 | @param [out] version Version number from the DD | ||
| 4607 | tablespace header. | ||
| 4608 | |||
| 4609 | @retval Operation outcome, false if no error, otherwise true. | ||
| 4610 | */ | ||
| 4611 | 23647 | static bool innobase_dict_get_server_version(uint *version) { | |
| 4612 | 23647 | return (fsp_header_dict_get_server_version(version)); | |
| 4613 | } | ||
| 4614 | |||
| 4615 | /** | ||
| 4616 | Store the current server version number into the | ||
| 4617 | header of the dictionary tablespace. | ||
| 4618 | |||
| 4619 | @retval Operation outcome, false if no error, otherwise true. | ||
| 4620 | */ | ||
| 4621 | 165 | static bool innobase_dict_set_server_version() { | |
| 4622 | /* Update the server version number, but leave the space version unchanged */ | ||
| 4623 | 165 | return (upgrade_space_version(dict_sys_t::s_dict_space_id, true)); | |
| 4624 | } | ||
| 4625 | |||
| 4626 | /** Start page tracking. | ||
| 4627 | @param[out] start_id LSN indicating when the tracking was started | ||
| 4628 | @return Operation status. | ||
| 4629 | @retval 0 Success | ||
| 4630 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4631 | ✗ | static int innobase_page_track_start(uint64_t *start_id) { | |
| 4632 | ✗ | if (srv_read_only_mode) { | |
| 4633 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4634 | ✗ | return ER_READ_ONLY_MODE; | |
| 4635 | } | ||
| 4636 | |||
| 4637 | ✗ | Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client(); | |
| 4638 | |||
| 4639 | ✗ | int err = ctx->start(false, start_id); | |
| 4640 | |||
| 4641 | ✗ | return (err); | |
| 4642 | } | ||
| 4643 | |||
| 4644 | /** Stop page tracking. | ||
| 4645 | @param[out] stop_id Stop LSN indicating when the tracking was stopped | ||
| 4646 | @return Operation status. | ||
| 4647 | @retval 0 Success | ||
| 4648 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4649 | ✗ | static int innobase_page_track_stop(uint64_t *stop_id) { | |
| 4650 | ✗ | if (srv_read_only_mode) { | |
| 4651 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4652 | ✗ | return ER_READ_ONLY_MODE; | |
| 4653 | } | ||
| 4654 | |||
| 4655 | ✗ | Page_Arch_Client_Ctx *ctx = arch_page_sys->get_sys_client(); | |
| 4656 | |||
| 4657 | ✗ | int err = ctx->stop(stop_id); | |
| 4658 | |||
| 4659 | ✗ | return (err); | |
| 4660 | } | ||
| 4661 | |||
| 4662 | /** Purge page tracking data. | ||
| 4663 | @param[in,out] purge_id Purge LSN initially indicating till where the data | ||
| 4664 | needs to be purged and finally updated to until where it was actually purged | ||
| 4665 | @return Operation status. | ||
| 4666 | @retval 0 Success | ||
| 4667 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4668 | ✗ | static int innobase_page_track_purge(uint64_t *purge_id) { | |
| 4669 | ✗ | if (srv_read_only_mode) { | |
| 4670 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4671 | ✗ | return ER_READ_ONLY_MODE; | |
| 4672 | } | ||
| 4673 | |||
| 4674 | ✗ | auto err = arch_page_sys->purge(purge_id); | |
| 4675 | |||
| 4676 | ✗ | return (err); | |
| 4677 | } | ||
| 4678 | |||
| 4679 | /** Fetch tracked pages. | ||
| 4680 | @param[in] cbk_func callback function return page IDs | ||
| 4681 | @param[in] cbk_ctx caller's context for callback | ||
| 4682 | @param[in,out] start_id SE specific sequence number [LSN for Innodb] from | ||
| 4683 | where the pages tracked would be returned. | ||
| 4684 | @note The range might get expanded and the actual start_id used for the | ||
| 4685 | querying will be updated. | ||
| 4686 | @param[in,out] stop_id SE specific sequence number [LSN for Innodb] | ||
| 4687 | until where the pages tracked would be returned. | ||
| 4688 | @note The range might get expanded and the actual stop_id used for the | ||
| 4689 | querying will be updated. | ||
| 4690 | @param[out] buffer allocated buffer to copy page IDs | ||
| 4691 | @param[in] buffer_len length of buffer in bytes | ||
| 4692 | @return Operation status. | ||
| 4693 | @retval 0 Success | ||
| 4694 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4695 | ✗ | static int innobase_page_track_get_page_ids(Page_Track_Callback cbk_func, | |
| 4696 | void *cbk_ctx, uint64_t *start_id, | ||
| 4697 | uint64_t *stop_id, | ||
| 4698 | unsigned char *buffer, | ||
| 4699 | size_t buffer_len) { | ||
| 4700 | ✗ | if (srv_read_only_mode) { | |
| 4701 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4702 | ✗ | return ER_READ_ONLY_MODE; | |
| 4703 | } | ||
| 4704 | |||
| 4705 | auto err = | ||
| 4706 | ✗ | arch_page_sys->get_pages(nullptr, cbk_func, cbk_ctx, *start_id, *stop_id, | |
| 4707 | buffer, static_cast<uint>(buffer_len)); | ||
| 4708 | |||
| 4709 | ✗ | if (err != 0) { | |
| 4710 | ✗ | DBUG_PRINT("page_archiver", ("Fetch Pages")); | |
| 4711 | ✗ | DBUG_PRINT("page_archiver", ("Can't fetch pages")); | |
| 4712 | } | ||
| 4713 | |||
| 4714 | ✗ | return (err); | |
| 4715 | } | ||
| 4716 | |||
| 4717 | /** Fetch approximate number of tracked pages in the given range. | ||
| 4718 | @param[in,out] start_id SE specific sequence number [LSN for Innodb] from | ||
| 4719 | where the pages tracked would be returned. | ||
| 4720 | @note the range might get expanded and the actual start_id used for the | ||
| 4721 | querying will be updated. | ||
| 4722 | @param[in,out] stop_id SE specific sequence number [LSN for Innodb] | ||
| 4723 | until where the pages tracked would be returned. | ||
| 4724 | @note the range might get expanded and the actual stop_id used for the | ||
| 4725 | querying will be updated. | ||
| 4726 | @param[out] num_pages number of pages tracked | ||
| 4727 | @return Operation status. | ||
| 4728 | @retval 0 Success | ||
| 4729 | @retval other ER_* mysql error. Get error details from THD. */ | ||
| 4730 | ✗ | static int innobase_page_track_get_num_page_ids(uint64_t *start_id, | |
| 4731 | uint64_t *stop_id, | ||
| 4732 | uint64_t *num_pages) { | ||
| 4733 | ✗ | if (srv_read_only_mode) { | |
| 4734 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4735 | ✗ | return ER_READ_ONLY_MODE; | |
| 4736 | } | ||
| 4737 | |||
| 4738 | ✗ | auto err = arch_page_sys->get_num_pages(*start_id, *stop_id, num_pages); | |
| 4739 | |||
| 4740 | ✗ | if (err != 0) { | |
| 4741 | ✗ | DBUG_PRINT("page_archiver", ("Fetch Pages")); | |
| 4742 | ✗ | DBUG_PRINT("page_archiver", ("Can't fetch pages")); | |
| 4743 | } | ||
| 4744 | |||
| 4745 | ✗ | return (err); | |
| 4746 | } | ||
| 4747 | |||
| 4748 | /** Fetch the page tracking status. | ||
| 4749 | @param[out] status vector of a pair of (ID, bool) where ID is the | ||
| 4750 | start/stop point and bool is true if the ID is a start point else false */ | ||
| 4751 | ✗ | static void innobase_page_track_get_status( | |
| 4752 | std::vector<std::pair<lsn_t, bool>> &status) { | ||
| 4753 | ✗ | if (srv_read_only_mode) { | |
| 4754 | ✗ | my_error(ER_READ_ONLY_MODE, MYF(0)); | |
| 4755 | ✗ | return; | |
| 4756 | } | ||
| 4757 | |||
| 4758 | ✗ | arch_page_sys->get_status(status); | |
| 4759 | } | ||
| 4760 | |||
| 4761 | /** Gives the file extension of an InnoDB single-table tablespace. */ | ||
| 4762 | static const char *ha_innobase_exts[] = {dot_ext[IBD], NullS}; | ||
| 4763 | |||
| 4764 | /** This function checks if the given db.tablename is a system table | ||
| 4765 | supported by Innodb and is used as an initializer for the data member | ||
| 4766 | is_supported_system_table of InnoDB storage engine handlerton. | ||
| 4767 | Except general_log and slow_log, currently all system tables are supported | ||
| 4768 | by InnoDB. Please don't add any SE-specific system tables here. | ||
| 4769 | |||
| 4770 | @param is_sql_layer_system_table if the supplied db.table_name is a SQL | ||
| 4771 | layer system table. | ||
| 4772 | |||
| 4773 | @return whether the table name is supported */ | ||
| 4774 | |||
| 4775 | 1072243 | static bool innobase_is_supported_system_table(const char *, const char *, | |
| 4776 | bool is_sql_layer_system_table) { | ||
| 4777 | // Currently InnoDB does not support any other SE specific system tables. | ||
| 4778 | 1072243 | return is_sql_layer_system_table; | |
| 4779 | } | ||
| 4780 | |||
| 4781 | /** Rotate the encrypted tablespace keys according to master key | ||
| 4782 | rotation. | ||
| 4783 | @return false on success, true on failure */ | ||
| 4784 | 3700 | bool innobase_encryption_key_rotation() { | |
| 4785 | 3700 | byte *master_key = nullptr; | |
| 4786 | 3700 | bool ret = false; | |
| 4787 | dberr_t err; | ||
| 4788 | |||
| 4789 | /* Pause here to try other locks while this thread holds the backup locks. */ | ||
| 4790 |
2/4✓ Branch 0 taken 3700 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3700 times.
✗ Branch 3 not taken.
|
3700 | DEBUG_SYNC_C("ib_pause_encryption_rotate"); |
| 4791 | |||
| 4792 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3700 times.
|
3700 | if (srv_read_only_mode) { |
| 4793 | ✗ | my_error(ER_INNODB_READ_ONLY, MYF(0)); | |
| 4794 | ✗ | return (true); | |
| 4795 | } | ||
| 4796 | |||
| 4797 | /* Take mutex as master_key_id is going to be changed. */ | ||
| 4798 |
1/2✓ Branch 0 taken 3700 times.
✗ Branch 1 not taken.
|
3700 | mutex_enter(&master_key_id_mutex); |
| 4799 | |||
| 4800 | /* Check if keyring loaded and the currently master key | ||
| 4801 | can be fetched. */ | ||
| 4802 |
3/4✓ Branch 0 taken 3700 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3573 times.
✓ Branch 3 taken 127 times.
|
3700 | if (Encryption::get_master_key_id() != Encryption::DEFAULT_MASTER_KEY_ID) { |
| 4803 | uint32_t master_key_id; | ||
| 4804 | |||
| 4805 | 3573 | Encryption::get_master_key(&master_key_id, &master_key); | |
| 4806 | |||
| 4807 |
2/2✓ Branch 0 taken 105 times.
✓ Branch 1 taken 3468 times.
|
3573 | if (master_key == nullptr) { |
| 4808 |
1/2✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
|
105 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 4809 | 105 | ret = true; | |
| 4810 | 105 | goto error_exit; | |
| 4811 | } | ||
| 4812 |
1/2✓ Branch 0 taken 3468 times.
✗ Branch 1 not taken.
|
3468 | my_free(master_key); |
| 4813 | } | ||
| 4814 | |||
| 4815 | 3595 | master_key = nullptr; | |
| 4816 | |||
| 4817 | /* Generate the new master key. */ | ||
| 4818 | 3595 | Encryption::create_master_key(&master_key); | |
| 4819 | |||
| 4820 |
2/2✓ Branch 0 taken 65 times.
✓ Branch 1 taken 3528 times.
|
3593 | if (master_key == nullptr) { |
| 4821 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 4822 | 65 | ret = true; | |
| 4823 | 65 | goto error_exit; | |
| 4824 | } | ||
| 4825 | |||
| 4826 | /* Rotate all IBD and IBU tablespace that need it. */ | ||
| 4827 |
2/4✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3488 times.
|
3528 | if (fil_encryption_rotate() > 0) { |
| 4828 | ✗ | my_free(master_key); | |
| 4829 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 4830 | ✗ | goto error_exit; | |
| 4831 | } | ||
| 4832 | |||
| 4833 |
1/2✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
|
3488 | err = log_encryption_on_master_key_changed(*log_sys); |
| 4834 | 3488 | ret = (err != DB_SUCCESS); | |
| 4835 | |||
| 4836 | /* If rotation failure, return error */ | ||
| 4837 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3488 times.
|
3488 | if (ret) { |
| 4838 | ✗ | my_free(master_key); | |
| 4839 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 4840 | ✗ | goto error_exit; | |
| 4841 | } | ||
| 4842 | |||
| 4843 | /* Rotate encrypted session temporary tablespaces */ | ||
| 4844 |
1/2✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
|
3488 | ibt::tbsp_pool->rotate_encryption_keys(); |
| 4845 | |||
| 4846 |
1/2✓ Branch 0 taken 3488 times.
✗ Branch 1 not taken.
|
3488 | my_free(master_key); |
| 4847 | |||
| 4848 | 3658 | error_exit: | |
| 4849 | /* Release the mutex. */ | ||
| 4850 |
1/2✓ Branch 0 taken 3658 times.
✗ Branch 1 not taken.
|
3658 | mutex_exit(&master_key_id_mutex); |
| 4851 | |||
| 4852 | 3658 | return (ret); | |
| 4853 | } | ||
| 4854 | |||
| 4855 | 11808 | bool innobase_fix_default_table_encryption(ulong encryption_option, bool is_server_starting) { | |
| 4856 |
2/2✓ Branch 0 taken 11768 times.
✓ Branch 1 taken 40 times.
|
11808 | if (!srv_read_only_mode) { |
| 4857 | 11768 | return fil_crypt_set_encrypt_tables( | |
| 4858 | 11768 | static_cast<enum_default_table_encryption>(encryption_option), is_server_starting); | |
| 4859 | } | ||
| 4860 | 40 | return false; | |
| 4861 | } | ||
| 4862 | |||
| 4863 | /** Fix the empty UUID of tablespaces like system, temp etc by generating | ||
| 4864 | a new master key and do key rotation. These tablespaces if encrypted | ||
| 4865 | during startup, will be encrypted with tablespace key which has empty UUID | ||
| 4866 | @return false on success, true on failure */ | ||
| 4867 | 11760 | bool innobase_fix_tablespaces_empty_uuid() { | |
| 4868 | #ifdef UNIV_DEBUG | ||
| 4869 | /* This API is called only after uuid is ready */ | ||
| 4870 | 11760 | srv_is_uuid_ready = true; | |
| 4871 | #endif /* UNIV_DEBUG */ | ||
| 4872 | |||
| 4873 | /* If we are in read only mode, we cannot do rotation but it | ||
| 4874 | is OK */ | ||
| 4875 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 11720 times.
|
11760 | if (srv_read_only_mode) { |
| 4876 | 40 | return (false); | |
| 4877 | } | ||
| 4878 | |||
| 4879 | /* We only need to handle the case when an encrypted tablespace | ||
| 4880 | is created at startup. If it is > 1, it means we already have fixed | ||
| 4881 | the UUID */ | ||
| 4882 |
3/4✓ Branch 0 taken 11720 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 356 times.
✓ Branch 3 taken 11364 times.
|
11720 | if (Encryption::get_master_key_id() > 1) { |
| 4883 | 356 | return (false); | |
| 4884 | } | ||
| 4885 | |||
| 4886 |
1/2✓ Branch 0 taken 11364 times.
✗ Branch 1 not taken.
|
11364 | if (!default_master_key_used) { |
| 4887 | 11364 | return (false); | |
| 4888 | } | ||
| 4889 | |||
| 4890 | ✗ | byte *master_key = nullptr; | |
| 4891 | uint32_t master_key_id; | ||
| 4892 | ✗ | Encryption::get_master_key(&master_key_id, &master_key); | |
| 4893 | |||
| 4894 | ✗ | if (master_key == nullptr) { | |
| 4895 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 4896 | ✗ | return (true); | |
| 4897 | } | ||
| 4898 | ✗ | my_free(master_key); | |
| 4899 | |||
| 4900 | ✗ | master_key = nullptr; | |
| 4901 | |||
| 4902 | /* Generate the new master key. */ | ||
| 4903 | ✗ | Encryption::create_master_key(&master_key); | |
| 4904 | |||
| 4905 | ✗ | if (master_key == nullptr) { | |
| 4906 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 4907 | ✗ | return (true); | |
| 4908 | } | ||
| 4909 | |||
| 4910 | /** Check if sys, temp need rotation to fix the empty uuid */ | ||
| 4911 | ✗ | space_id_vec space_ids; | |
| 4912 | |||
| 4913 | ✗ | space_ids.push_back(srv_sys_space.space_id()); | |
| 4914 | ✗ | space_ids.push_back(srv_tmp_space.space_id()); | |
| 4915 | ✗ | space_ids.push_back(dict_sys_t::s_dict_space_id); | |
| 4916 | |||
| 4917 | #ifdef UNIV_DEBUG | ||
| 4918 | /* Currently all session temp tablespaces that use empty uuid | ||
| 4919 | are destroyed. So if there is encrypted sesion temp tablespace | ||
| 4920 | we assert here */ | ||
| 4921 | ✗ | const auto find_encrypted = [&](const ibt::Tablespace *ts) { | |
| 4922 | ✗ | if (ts->is_encrypted()) { | |
| 4923 | ✗ | ut_ad(0); | |
| 4924 | } | ||
| 4925 | ✗ | }; | |
| 4926 | |||
| 4927 | ✗ | ibt::tbsp_pool->iterate_active_tbsp(find_encrypted); | |
| 4928 | #endif /* UNIV_DEBUG */ | ||
| 4929 | |||
| 4930 | ✗ | undo::spaces->s_lock(); | |
| 4931 | ✗ | for (auto undo_space : undo::spaces->m_spaces) { | |
| 4932 | /* We already added system tablespace */ | ||
| 4933 | ✗ | if (undo_space->id() == TRX_SYS_SPACE) { | |
| 4934 | ✗ | continue; | |
| 4935 | } | ||
| 4936 | ✗ | space_ids.push_back(undo_space->id()); | |
| 4937 | } | ||
| 4938 | ✗ | undo::spaces->s_unlock(); | |
| 4939 | |||
| 4940 | /* Rotate log tablespace */ | ||
| 4941 | |||
| 4942 | ✗ | my_free(master_key); | |
| 4943 | |||
| 4944 | ✗ | return (false); | |
| 4945 | } | ||
| 4946 | |||
| 4947 | /** Enable or Disable SE write ahead logging. | ||
| 4948 | @param[in] thd connection THD | ||
| 4949 | @param[in] enable enable/disable redo logging | ||
| 4950 | @return true iff failed. */ | ||
| 4951 | 38 | static bool innobase_redo_set_state(THD *thd, bool enable) { | |
| 4952 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (srv_read_only_mode) { |
| 4953 | ✗ | my_error(ER_INNODB_READ_ONLY, MYF(0)); | |
| 4954 | ✗ | return (true); | |
| 4955 | } | ||
| 4956 | |||
| 4957 | 38 | int err = 0; | |
| 4958 | |||
| 4959 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20 times.
|
38 | if (enable) { |
| 4960 | 18 | err = mtr_t::s_logging.enable(thd); | |
| 4961 | } else { | ||
| 4962 | 20 | err = mtr_t::s_logging.disable(thd); | |
| 4963 | } | ||
| 4964 | |||
| 4965 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 36 times.
|
38 | if (err != 0) { |
| 4966 | 2 | return (true); | |
| 4967 | } | ||
| 4968 | |||
| 4969 | 36 | set_srv_redo_log(enable); | |
| 4970 | 36 | return (false); | |
| 4971 | } | ||
| 4972 | |||
| 4973 | /** Return partitioning flags. */ | ||
| 4974 | 2102734 | static uint innobase_partition_flags() { | |
| 4975 | return (HA_CAN_EXCHANGE_PARTITION | HA_CANNOT_PARTITION_FK | | ||
| 4976 | 2102734 | HA_TRUNCATE_PARTITION_PRECLOSE); | |
| 4977 | } | ||
| 4978 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4979 | |||
| 4980 | /** Update log_checksum_algorithm_ptr with a pointer to the function | ||
| 4981 | corresponding to whether checksums are enabled. | ||
| 4982 | @param[in] check whether redo log block checksums are enabled */ | ||
| 4983 | #ifndef UNIV_HOTBACKUP | ||
| 4984 | static | ||
| 4985 | #endif /* !UNIV_HOTBACKUP */ | ||
| 4986 | void | ||
| 4987 | 12034 | innodb_log_checksums_func_update(bool check) { | |
| 4988 |
2/2✓ Branch 0 taken 12030 times.
✓ Branch 1 taken 4 times.
|
12034 | log_checksum_algorithm_ptr.store(check ? log_block_calc_checksum_crc32 |
| 4989 | : log_block_calc_checksum_none); | ||
| 4990 | 12034 | } | |
| 4991 | |||
| 4992 | #ifndef UNIV_HOTBACKUP | ||
| 4993 | |||
| 4994 | /** Minimum expected tablespace size. (5M) */ | ||
| 4995 | static const ulint MIN_EXPECTED_TABLESPACE_SIZE = 5 * 1024 * 1024; | ||
| 4996 | |||
| 4997 | /** Validate innodb_undo_tablespaces. Log a warning if it was set | ||
| 4998 | explicitly. */ | ||
| 4999 | 12033 | static void innodb_undo_tablespaces_deprecate() { | |
| 5000 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12033 times.
|
12033 | if (sysvar_source_svc == nullptr) { |
| 5001 | ✗ | return; | |
| 5002 | } | ||
| 5003 | |||
| 5004 | static const char *variable_name = "innodb_undo_tablespaces"; | ||
| 5005 | enum enum_variable_source source; | ||
| 5006 | |||
| 5007 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12033 times.
|
12033 | if (sysvar_source_svc->get(variable_name, |
| 5008 |
1/2✓ Branch 0 taken 12033 times.
✗ Branch 1 not taken.
|
12033 | static_cast<unsigned int>(strlen(variable_name)), |
| 5009 | &source)) { | ||
| 5010 | ✗ | return; | |
| 5011 | } | ||
| 5012 | |||
| 5013 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 12025 times.
|
12033 | if (source != COMPILED) { |
| 5014 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | ib::warn(ER_IB_MSG_DEPRECATED_INNODB_UNDO_TABLESPACES); |
| 5015 | 8 | srv_undo_tablespaces = FSP_IMPLICIT_UNDO_TABLESPACES; | |
| 5016 | } | ||
| 5017 | } | ||
| 5018 | |||
| 5019 | /** Validate innodb_parallel_doublewrite_path. Log a warning if it was set | ||
| 5020 | explicitly. */ | ||
| 5021 | 12027 | static void innodb_parallel_doublewrite_path_deprecate() { | |
| 5022 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | if (sysvar_source_svc != nullptr) { |
| 5023 | static const char *variable_name = "innodb_parallel_doublewrite_path"; | ||
| 5024 | enum enum_variable_source source; | ||
| 5025 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | if (!sysvar_source_svc->get( |
| 5026 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | variable_name, static_cast<unsigned int>(strlen(variable_name)), |
| 5027 | &source)) { | ||
| 5028 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12026 times.
|
12027 | if (source != COMPILED) { |
| 5029 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DOUBLEWRITE_PATH); |
| 5030 | } | ||
| 5031 | } | ||
| 5032 | } | ||
| 5033 | 12027 | } | |
| 5034 | |||
| 5035 | /** Validate innodb_parallel_dblwr_encrypt. Log a warning if it was set | ||
| 5036 | explicitly. */ | ||
| 5037 | 12030 | static void innodb_parallel_dblwr_encrypt_deprecate() { | |
| 5038 |
1/2✓ Branch 0 taken 12030 times.
✗ Branch 1 not taken.
|
12030 | if (sysvar_source_svc != nullptr) { |
| 5039 | static const char *variable_name = "innodb_parallel_dblwr_encrypt"; | ||
| 5040 | enum enum_variable_source source; | ||
| 5041 |
1/2✓ Branch 0 taken 12030 times.
✗ Branch 1 not taken.
|
12030 | if (!sysvar_source_svc->get( |
| 5042 |
1/2✓ Branch 0 taken 12030 times.
✗ Branch 1 not taken.
|
12030 | variable_name, static_cast<unsigned int>(strlen(variable_name)), |
| 5043 | &source)) { | ||
| 5044 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12026 times.
|
12030 | if (source != COMPILED) { |
| 5045 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ib::warn(ER_IB_MSG_DEPRECATED_INNODB_PARALLEL_DBLWR_ENCRYPT); |
| 5046 | } | ||
| 5047 | } | ||
| 5048 | } | ||
| 5049 | 12030 | } | |
| 5050 | |||
| 5051 | /** Initialize and normalize innodb_buffer_pool_size. */ | ||
| 5052 | 12027 | static void innodb_buffer_pool_size_init() { | |
| 5053 | #ifdef UNIV_DEBUG | ||
| 5054 | 12027 | ulong srv_buf_pool_instances_org = srv_buf_pool_instances; | |
| 5055 | #endif /* UNIV_DEBUG */ | ||
| 5056 | |||
| 5057 | /* If innodb_dedicated_server == ON */ | ||
| 5058 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
12027 | if (srv_dedicated_server && sysvar_source_svc != nullptr) { |
| 5059 | static const char *variable_name = "innodb_buffer_pool_size"; | ||
| 5060 | enum enum_variable_source source; | ||
| 5061 | ✗ | if (!sysvar_source_svc->get( | |
| 5062 | ✗ | variable_name, static_cast<unsigned int>(strlen(variable_name)), | |
| 5063 | &source)) { | ||
| 5064 | ✗ | if (source == COMPILED) { | |
| 5065 | ✗ | double server_mem = get_sys_mem(); | |
| 5066 | |||
| 5067 | ✗ | if (server_mem < 1.0) { | |
| 5068 | ; | ||
| 5069 | ✗ | } else if (server_mem <= 4.0) { | |
| 5070 | ✗ | srv_buf_pool_size = static_cast<ulint>(server_mem * 0.5 * GB); | |
| 5071 | } else | ||
| 5072 | ✗ | srv_buf_pool_size = static_cast<ulint>(server_mem * 0.75 * GB); | |
| 5073 | } else { | ||
| 5074 | ✗ | ib::warn(ER_IB_MSG_533) | |
| 5075 | << "Option innodb_dedicated_server" | ||
| 5076 | " is ignored for" | ||
| 5077 | " innodb_buffer_pool_size because" | ||
| 5078 | ✗ | " innodb_buffer_pool_size=" | |
| 5079 | ✗ | << srv_buf_pool_curr_size << " is specified explicitly."; | |
| 5080 | } | ||
| 5081 | } | ||
| 5082 | } | ||
| 5083 | |||
| 5084 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 12004 times.
|
12027 | if (srv_buf_pool_size >= BUF_POOL_SIZE_THRESHOLD) { |
| 5085 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 15 times.
|
23 | if (srv_buf_pool_instances == srv_buf_pool_instances_default) { |
| 5086 | #if defined(_WIN32) && !defined(_WIN64) | ||
| 5087 | /* Do not allocate too large of a buffer pool on | ||
| 5088 | Windows 32-bit systems, which can have trouble | ||
| 5089 | allocating larger single contiguous memory blocks. */ | ||
| 5090 | srv_buf_pool_instances = | ||
| 5091 | std::min(static_cast<ulong>(MAX_BUFFER_POOLS), | ||
| 5092 | static_cast<ulong>(srv_buf_pool_size / (128 * 1024 * 1024))); | ||
| 5093 | #else /* defined(_WIN32) && !defined(_WIN64) */ | ||
| 5094 | /* Default to 8 instances when size > 1GB. */ | ||
| 5095 | 8 | srv_buf_pool_instances = 8; | |
| 5096 | #endif /* defined(_WIN32) && !defined(_WIN64) */ | ||
| 5097 | } | ||
| 5098 | } else { | ||
| 5099 | /* If buffer pool is less than 1 GiB, assume fewer | ||
| 5100 | threads. Also use only one buffer pool instance. */ | ||
| 5101 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12000 times.
|
12004 | if (srv_buf_pool_instances != srv_buf_pool_instances_default && |
| 5102 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | srv_buf_pool_instances != 1) { |
| 5103 | /* We can't distinguish whether the user has explicitly | ||
| 5104 | started mysqld with --innodb-buffer-pool-instances=0, | ||
| 5105 | (srv_buf_pool_instances_default is 0) or has not | ||
| 5106 | specified that option at all. Thus we have the | ||
| 5107 | limitation that if the user started with =0, we | ||
| 5108 | will not emit a warning here, but we should actually | ||
| 5109 | do so. */ | ||
| 5110 | 2 | ib::info(ER_IB_MSG_534) | |
| 5111 | << "Adjusting innodb_buffer_pool_instances" | ||
| 5112 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " from " |
| 5113 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | << srv_buf_pool_instances |
| 5114 | << " to 1" | ||
| 5115 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " since innodb_buffer_pool_size is less than " |
| 5116 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | << BUF_POOL_SIZE_THRESHOLD / (1024 * 1024) << " MiB"; |
| 5117 | } | ||
| 5118 | |||
| 5119 | 12004 | srv_buf_pool_instances = 1; | |
| 5120 | } | ||
| 5121 | |||
| 5122 | #ifdef UNIV_DEBUG | ||
| 5123 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12026 times.
|
12027 | if (srv_buf_pool_debug && |
| 5124 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | srv_buf_pool_instances_org != srv_buf_pool_instances_default) { |
| 5125 | 1 | srv_buf_pool_instances = srv_buf_pool_instances_org; | |
| 5126 | }; | ||
| 5127 | #endif /* UNIV_DEBUG */ | ||
| 5128 | |||
| 5129 | 12027 | srv_buf_pool_chunk_unit = buf_pool_adjust_chunk_unit(srv_buf_pool_chunk_unit); | |
| 5130 | 12027 | srv_buf_pool_size = buf_pool_size_align(srv_buf_pool_size); | |
| 5131 | |||
| 5132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_ad(srv_buf_pool_chunk_unit >= srv_buf_pool_chunk_unit_min); |
| 5133 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_ad(srv_buf_pool_chunk_unit <= srv_buf_pool_chunk_unit_max); |
| 5134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_ad(srv_buf_pool_chunk_unit % srv_buf_pool_chunk_unit_blk_sz == 0); |
| 5135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_ad(srv_buf_pool_chunk_unit % UNIV_PAGE_SIZE == 0); |
| 5136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_ad(0 == |
| 5137 | srv_buf_pool_size % (srv_buf_pool_chunk_unit * srv_buf_pool_instances)); | ||
| 5138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_ad(srv_buf_pool_chunk_unit * srv_buf_pool_instances <= srv_buf_pool_size); |
| 5139 | |||
| 5140 | 12027 | srv_buf_pool_curr_size = srv_buf_pool_size; | |
| 5141 | |||
| 5142 | /* Do not enable backoff algorithm for small buffer pool. */ | ||
| 5143 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12025 times.
|
12027 | if (!innodb_empty_free_list_algorithm_allowed( |
| 5144 | static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm))) { | ||
| 5145 | 2 | sql_print_information( | |
| 5146 | "InnoDB: innodb_empty_free_list_algorithm has been changed to legacy " | ||
| 5147 | "because of small buffer pool size. In order to use backoff, " | ||
| 5148 | "increase buffer pool at least up to 20MB.\n"); | ||
| 5149 | 2 | srv_empty_free_list_algorithm = SRV_EMPTY_FREE_LIST_LEGACY; | |
| 5150 | } | ||
| 5151 | 12027 | } | |
| 5152 | |||
| 5153 | template <size_t N> | ||
| 5154 | 72162 | static bool innodb_variable_is_set(const char (&var_name)[N]) { | |
| 5155 | enum enum_variable_source source; | ||
| 5156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36081 times.
|
72162 | ut_a(sysvar_source_svc != nullptr); |
| 5157 |
1/2✓ Branch 0 taken 36081 times.
✗ Branch 1 not taken.
|
72162 | const auto svc_result = sysvar_source_svc->get(var_name, N - 1, &source); |
| 5158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36081 times.
|
72162 | ut_a(!svc_result); |
| 5159 | 72162 | return source != COMPILED; | |
| 5160 | } | ||
| 5161 | |||
| 5162 | 12027 | static bool innodb_redo_log_capacity_is_set() { | |
| 5163 | 12027 | return innodb_variable_is_set("innodb_redo_log_capacity"); | |
| 5164 | } | ||
| 5165 | |||
| 5166 | 12027 | bool innodb_log_file_size_is_set() { | |
| 5167 | 12027 | return innodb_variable_is_set("innodb_log_file_size"); | |
| 5168 | } | ||
| 5169 | |||
| 5170 | 12027 | bool innodb_log_n_files_is_set() { | |
| 5171 | 12027 | return innodb_variable_is_set("innodb_log_files_in_group"); | |
| 5172 | } | ||
| 5173 | |||
| 5174 | /** Initialize srv_redo_log_capacity / srv_redo_log_capacity_used. */ | ||
| 5175 | 12027 | static void innodb_redo_log_capacity_init() { | |
| 5176 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | DBUG_TRACE; |
| 5177 | |||
| 5178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(MB % UNIV_PAGE_SIZE == 0); |
| 5179 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_redo_log_capacity % MB == 0); |
| 5180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_redo_log_capacity > 0); |
| 5181 | |||
| 5182 | 12027 | srv_redo_log_capacity_used = srv_redo_log_capacity; | |
| 5183 | |||
| 5184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | if (sysvar_source_svc == nullptr) { |
| 5185 | ✗ | return; | |
| 5186 | } | ||
| 5187 | |||
| 5188 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | const bool file_size_set = innodb_log_file_size_is_set(); |
| 5189 | |||
| 5190 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | const bool n_files_set = innodb_log_n_files_is_set(); |
| 5191 | |||
| 5192 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | bool capacity_set = innodb_redo_log_capacity_is_set(); |
| 5193 | |||
| 5194 |
2/2✓ Branch 0 taken 11790 times.
✓ Branch 1 taken 237 times.
|
12027 | if (capacity_set) { |
| 5195 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11787 times.
|
11790 | if (file_size_set) { |
| 5196 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | ib::warn(ER_IB_MSG_LOG_PARAMS_FILE_SIZE_UNUSED); |
| 5197 | } | ||
| 5198 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11788 times.
|
11790 | if (n_files_set) { |
| 5199 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ib::warn(ER_IB_MSG_LOG_PARAMS_N_FILES_UNUSED); |
| 5200 | } | ||
| 5201 | } else { | ||
| 5202 |
4/4✓ Branch 0 taken 234 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 232 times.
|
237 | if (file_size_set || n_files_set) { |
| 5203 | 5 | srv_redo_log_capacity_used = srv_log_file_size * srv_log_n_files; | |
| 5204 | 5 | capacity_set = true; // do not change it in dedicated_server mode | |
| 5205 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ib::warn(ER_IB_MSG_LOG_PARAMS_LEGACY_USAGE, srv_redo_log_capacity_used); |
| 5206 | } | ||
| 5207 | } | ||
| 5208 | |||
| 5209 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | if (srv_dedicated_server) { |
| 5210 | double auto_buf_pool_size_in_gb; | ||
| 5211 | static const char *var_name_buf_pool_size = "innodb_buffer_pool_size"; | ||
| 5212 | enum enum_variable_source source; | ||
| 5213 | |||
| 5214 | ✗ | auto_buf_pool_size_in_gb = static_cast<double>(srv_buf_pool_size / GB); | |
| 5215 | |||
| 5216 | /* If user has set buffer pool size in .cnf, we will not use it as base | ||
| 5217 | line for log_file_size auto tuning, instead, we will get the value of | ||
| 5218 | possible tuned buffer pool size. */ | ||
| 5219 | ✗ | if (!sysvar_source_svc->get( | |
| 5220 | var_name_buf_pool_size, | ||
| 5221 | ✗ | static_cast<unsigned int>(strlen(var_name_buf_pool_size)), | |
| 5222 | &source)) { | ||
| 5223 | ✗ | if (source != COMPILED) { | |
| 5224 | ✗ | double server_mem = get_sys_mem(); | |
| 5225 | |||
| 5226 | #ifdef UNIV_DEBUG_DEDICATED | ||
| 5227 | server_mem = srv_debug_system_mem_size / GB; | ||
| 5228 | #endif /* UNIV_DEBUG_DEDICATED */ | ||
| 5229 | |||
| 5230 | ✗ | if (server_mem < 1.0) { | |
| 5231 | ; | ||
| 5232 | ✗ | } else if (server_mem <= 4.0) { | |
| 5233 | ✗ | auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.5); | |
| 5234 | } else | ||
| 5235 | ✗ | auto_buf_pool_size_in_gb = static_cast<double>(server_mem * 0.75); | |
| 5236 | } | ||
| 5237 | } | ||
| 5238 | |||
| 5239 | ✗ | if (!capacity_set) { | |
| 5240 | /* We update srv_redo_log_capacity (underlying sysvar variable), | ||
| 5241 | because that is what innodb_dedicated_server is expected to do. */ | ||
| 5242 | ✗ | if (auto_buf_pool_size_in_gb < 1.0) { | |
| 5243 | ✗ | ut_ad(srv_redo_log_capacity == 100 * 1024 * 1024); | |
| 5244 | ✗ | } else if (auto_buf_pool_size_in_gb < 8.0) { | |
| 5245 | ✗ | srv_redo_log_capacity = | |
| 5246 | ✗ | static_cast<ulong>(round(auto_buf_pool_size_in_gb)) * 512ULL * MB; | |
| 5247 | ✗ | } else if (auto_buf_pool_size_in_gb <= 128.0) { | |
| 5248 | ✗ | srv_redo_log_capacity = | |
| 5249 | ✗ | static_cast<ulong>(round(auto_buf_pool_size_in_gb * 0.75)) * GB; | |
| 5250 | } else { | ||
| 5251 | ✗ | constexpr os_offset_t LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER = 128 * GB; | |
| 5252 | |||
| 5253 | static_assert( | ||
| 5254 | LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER <= LOG_CAPACITY_MAX, | ||
| 5255 | "Redo log capacity, for the dedicated server, is too big."); | ||
| 5256 | |||
| 5257 | ✗ | srv_redo_log_capacity = LOG_CAPACITY_FOR_BIG_DEDICATED_SERVER; | |
| 5258 | } | ||
| 5259 | ✗ | srv_redo_log_capacity_used = srv_redo_log_capacity; | |
| 5260 | |||
| 5261 | } else { | ||
| 5262 | ✗ | ut_a(srv_redo_log_capacity_used % MB == 0); | |
| 5263 | ✗ | ib::warn(ER_IB_MSG_LOG_PARAMS_DEDICATED_SERVER_IGNORED, | |
| 5264 | ✗ | ulonglong{srv_redo_log_capacity_used / MB}); | |
| 5265 | } | ||
| 5266 | } | ||
| 5267 | |||
| 5268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(LOG_CAPACITY_MIN <= srv_redo_log_capacity_used); |
| 5269 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_redo_log_capacity_used <= LOG_CAPACITY_MAX); |
| 5270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_redo_log_capacity_used % MB == 0); |
| 5271 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | } |
| 5272 | |||
| 5273 | /** Initialize, validate and normalize the InnoDB startup parameters. | ||
| 5274 | @return failure code | ||
| 5275 | @retval 0 on success | ||
| 5276 | @retval HA_ERR_OUT_OF_MEM when out of memory | ||
| 5277 | @retval HA_ERR_INITIALIZATION when some parameters are out of range */ | ||
| 5278 | 12035 | static int innodb_init_params() { | |
| 5279 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | DBUG_TRACE; |
| 5280 | |||
| 5281 | static char current_dir[3]; | ||
| 5282 | char *default_path; | ||
| 5283 | |||
| 5284 | /* First calculate the default path for innodb_data_home_dir etc., | ||
| 5285 | in case the user has not given any value. */ | ||
| 5286 | |||
| 5287 | /* It's better to use current lib, to keep paths short */ | ||
| 5288 | 12035 | current_dir[0] = FN_CURLIB; | |
| 5289 | 12035 | current_dir[1] = FN_LIBCHAR; | |
| 5290 | 12035 | current_dir[2] = 0; | |
| 5291 | 12035 | default_path = current_dir; | |
| 5292 | |||
| 5293 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | std::string mysqld_datadir{default_path}; |
| 5294 | |||
| 5295 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | MySQL_datadir_path = Fil_path{mysqld_datadir}; |
| 5296 | |||
| 5297 | /* Validate, normalize and interpret the InnoDB start-up parameters. */ | ||
| 5298 | |||
| 5299 | /* The default dir for data files is the datadir of MySQL */ | ||
| 5300 | |||
| 5301 | 12035 | srv_data_home = | |
| 5302 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 43 times.
|
45 | (innobase_data_home_dir == nullptr || *innobase_data_home_dir == '\0') |
| 5303 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 11990 times.
|
12080 | ? default_path |
| 5304 | : innobase_data_home_dir; | ||
| 5305 | 12035 | Fil_path::normalize(srv_data_home); | |
| 5306 | |||
| 5307 | /* Validate the undo directory. */ | ||
| 5308 |
3/4✓ Branch 0 taken 48 times.
✓ Branch 1 taken 11987 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
|
12035 | if (srv_undo_dir == nullptr || srv_undo_dir[0] == 0) { |
| 5309 | 11987 | srv_undo_dir = default_path; | |
| 5310 | } else { | ||
| 5311 | 48 | Fil_path::normalize(srv_undo_dir); | |
| 5312 | } | ||
| 5313 | |||
| 5314 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | MySQL_undo_path = Fil_path{srv_undo_dir}; |
| 5315 | |||
| 5316 |
4/6✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12035 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12034 times.
|
12035 | if (MySQL_undo_path.is_ancestor(default_path)) { |
| 5317 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY_LOCATION); |
| 5318 | 1 | return HA_ERR_INITIALIZATION; | |
| 5319 | } | ||
| 5320 | |||
| 5321 | /* Validate the temp directory */ | ||
| 5322 |
2/2✓ Branch 0 taken 12027 times.
✓ Branch 1 taken 7 times.
|
12034 | if (ibt::srv_temp_dir == nullptr) { |
| 5323 | 12027 | ibt::srv_temp_dir = default_path; | |
| 5324 | } else { | ||
| 5325 | os_file_type_t type; | ||
| 5326 | bool exists; | ||
| 5327 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | os_file_status(ibt::srv_temp_dir, &exists, &type); |
| 5328 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
7 | if (!exists || type != OS_FILE_TYPE_DIR) { |
| 5329 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_DOESNT_EXIST) |
| 5330 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | << "Invalid innodb_temp_tablespaces_dir: " << ibt::srv_temp_dir |
| 5331 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | << ". Directory doesn't exist or not valid"; |
| 5332 | 5 | return HA_ERR_INITIALIZATION; | |
| 5333 | } | ||
| 5334 | |||
| 5335 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | Fil_path temp_dir(ibt::srv_temp_dir); |
| 5336 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (temp_dir.path().empty()) { |
| 5337 | ✗ | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_EMPTY) | |
| 5338 | ✗ | << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir | |
| 5339 | ✗ | << ". Path cannot be empty"; | |
| 5340 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5341 | } | ||
| 5342 | |||
| 5343 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (strchr(ibt::srv_temp_dir, ';')) { |
| 5344 | ✗ | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_CONTAINS_SEMICOLON) | |
| 5345 | ✗ | << "Invalid innodb_temp_tablespaces dir: " << ibt::srv_temp_dir | |
| 5346 | ✗ | << ". Path cannot contain ;"; | |
| 5347 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5348 | } | ||
| 5349 | |||
| 5350 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (MySQL_datadir_path.is_ancestor( |
| 5351 |
3/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
8 | Fil_path::get_real_path(temp_dir.path()))) { |
| 5352 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | ib::error(ER_IB_ERR_TEMP_TABLESPACE_DIR_SUBDIR_OF_DATADIR) |
| 5353 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | << "Invalid innodb_temp_tablespaces_dir=" << ibt::srv_temp_dir |
| 5354 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | << ". This path should not be a subdirectory of the datadir."; |
| 5355 | 2 | return HA_ERR_INITIALIZATION; | |
| 5356 | } | ||
| 5357 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | } |
| 5358 | |||
| 5359 | 12029 | Fil_path::normalize(ibt::srv_temp_dir); | |
| 5360 | |||
| 5361 | /* The default dir for log files is the datadir of MySQL */ | ||
| 5362 | |||
| 5363 |
2/2✓ Branch 0 taken 12019 times.
✓ Branch 1 taken 10 times.
|
12029 | if (srv_log_group_home_dir == nullptr) { |
| 5364 | 12019 | srv_log_group_home_dir = default_path; | |
| 5365 | } | ||
| 5366 | 12029 | Fil_path::normalize(srv_log_group_home_dir); | |
| 5367 | |||
| 5368 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12028 times.
|
12029 | if (strchr(srv_log_group_home_dir, ';')) { |
| 5369 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_LOG_GROUP_HOME_DIR); |
| 5370 | 1 | return HA_ERR_INITIALIZATION; | |
| 5371 | } | ||
| 5372 | |||
| 5373 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12028 times.
|
12028 | if (strchr(srv_undo_dir, ';')) { |
| 5374 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_INNODB_UNDO_DIRECTORY); | |
| 5375 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5376 | } | ||
| 5377 | |||
| 5378 | if (!is_filename_allowed(srv_buf_dump_filename, strlen(srv_buf_dump_filename), | ||
| 5379 | false)) { | ||
| 5380 | log_errlog(ERROR_LEVEL, ER_INNODB_ILLEGAL_COLON_IN_POOL); | ||
| 5381 | return HA_ERR_INITIALIZATION; | ||
| 5382 | } | ||
| 5383 | |||
| 5384 | /* Check that the value of system variable innodb_page_size was | ||
| 5385 | set correctly. Its value was put into srv_page_size. If valid, | ||
| 5386 | return the associated srv_page_size_shift. */ | ||
| 5387 | 12028 | srv_page_size_shift = page_size_validate(srv_page_size); | |
| 5388 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12027 times.
|
12028 | if (!srv_page_size_shift) { |
| 5389 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | log_errlog(ERROR_LEVEL, ER_INNODB_INVALID_PAGE_SIZE, srv_page_size); |
| 5390 | 1 | return HA_ERR_INITIALIZATION; | |
| 5391 | } | ||
| 5392 | |||
| 5393 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_log_buffer_size % OS_FILE_LOG_BLOCK_SIZE == 0); |
| 5394 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_log_buffer_size > 0); |
| 5395 | |||
| 5396 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_log_write_ahead_size % OS_FILE_LOG_BLOCK_SIZE == 0); |
| 5397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_a(srv_log_write_ahead_size > 0); |
| 5398 | |||
| 5399 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | assert(innodb_change_buffering <= IBUF_USE_ALL); |
| 5400 | |||
| 5401 | /* Check that interdependent parameters have sane values. */ | ||
| 5402 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | if (srv_max_buf_pool_modified_pct < srv_max_dirty_pages_pct_lwm) { |
| 5403 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_DIRTY_WATER_MARK_NOT_LOW, | |
| 5404 | srv_max_buf_pool_modified_pct); | ||
| 5405 | ✗ | srv_max_dirty_pages_pct_lwm = srv_max_buf_pool_modified_pct; | |
| 5406 | } | ||
| 5407 | |||
| 5408 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | if (srv_max_io_capacity == SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT) { |
| 5409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | if (srv_io_capacity >= SRV_MAX_IO_CAPACITY_LIMIT / 2) { |
| 5410 | /* Avoid overflow. */ | ||
| 5411 | ✗ | srv_max_io_capacity = SRV_MAX_IO_CAPACITY_LIMIT; | |
| 5412 | } else { | ||
| 5413 | /* The user has not set the value. We should | ||
| 5414 | set it based on innodb_io_capacity. */ | ||
| 5415 | 12027 | srv_max_io_capacity = std::max(2 * srv_io_capacity, 2000UL); | |
| 5416 | } | ||
| 5417 | |||
| 5418 | ✗ | } else if (srv_max_io_capacity < srv_io_capacity) { | |
| 5419 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_IO_CAPACITY_EXCEEDS_MAX, | |
| 5420 | srv_max_io_capacity); | ||
| 5421 | ✗ | srv_io_capacity = srv_max_io_capacity; | |
| 5422 | } | ||
| 5423 | |||
| 5424 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11976 times.
|
12027 | if (UNIV_PAGE_SIZE_DEF != srv_page_size) { |
| 5425 |
1/2✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
|
102 | ib::warn(ER_IB_MSG_538) |
| 5426 | << "innodb-page-size has been changed from the" | ||
| 5427 |
1/2✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
|
51 | " default value " |
| 5428 |
4/8✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 51 times.
✗ Branch 7 not taken.
|
51 | << UNIV_PAGE_SIZE_DEF << " to " << srv_page_size << "."; |
| 5429 | } | ||
| 5430 | |||
| 5431 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12008 times.
|
12027 | if (srv_log_write_ahead_size > srv_page_size) { |
| 5432 | 19 | srv_log_write_ahead_size = srv_page_size; | |
| 5433 | } else { | ||
| 5434 | 12008 | ulong srv_log_write_ahead_size_tmp = OS_FILE_LOG_BLOCK_SIZE; | |
| 5435 | |||
| 5436 |
2/2✓ Branch 0 taken 48032 times.
✓ Branch 1 taken 12008 times.
|
60040 | while (srv_log_write_ahead_size_tmp < srv_log_write_ahead_size) { |
| 5437 | 48032 | srv_log_write_ahead_size_tmp = srv_log_write_ahead_size_tmp * 2; | |
| 5438 | } | ||
| 5439 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12008 times.
|
12008 | if (srv_log_write_ahead_size_tmp != srv_log_write_ahead_size) { |
| 5440 | ✗ | srv_log_write_ahead_size = srv_log_write_ahead_size_tmp / 2; | |
| 5441 | } | ||
| 5442 | } | ||
| 5443 | |||
| 5444 | 12027 | srv_buf_pool_size = srv_buf_pool_curr_size; | |
| 5445 | |||
| 5446 | 12027 | innodb_log_checksums_func_update(srv_log_checksums); | |
| 5447 | |||
| 5448 | #ifdef HAVE_LINUX_LARGE_PAGES | ||
| 5449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | if ((os_use_large_pages = opt_large_pages)) { |
| 5450 | ✗ | os_large_page_size = opt_large_page_size; | |
| 5451 | } | ||
| 5452 | #endif /* HAVE_LINUX_LARGE_PAGES */ | ||
| 5453 | |||
| 5454 | 12027 | row_rollback_on_timeout = innobase_rollback_on_timeout; | |
| 5455 | |||
| 5456 |
2/2✓ Branch 0 taken 12024 times.
✓ Branch 1 taken 3 times.
|
12027 | if (innobase_open_files < 10) { |
| 5457 | 12024 | innobase_open_files = 300; | |
| 5458 |
4/4✓ Branch 0 taken 12001 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 11995 times.
✓ Branch 3 taken 6 times.
|
12024 | if (srv_file_per_table && table_cache_size > 300) { |
| 5459 | 11995 | innobase_open_files = table_cache_size; | |
| 5460 | } | ||
| 5461 | } | ||
| 5462 | |||
| 5463 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12026 times.
|
12027 | if (innobase_open_files > (long)open_files_limit) { |
| 5464 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | ib::warn(ER_IB_MSG_539) << "innodb_open_files should not be greater" |
| 5465 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " than the open_files_limit.\n"; |
| 5466 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (innobase_open_files > (long)table_cache_size) { |
| 5467 | 1 | innobase_open_files = table_cache_size; | |
| 5468 | } | ||
| 5469 | } | ||
| 5470 | |||
| 5471 | 12027 | srv_innodb_status = innobase_create_status_file; | |
| 5472 | |||
| 5473 | /* Round up ddl:fts_parser_threads to nearest power of 2 number */ | ||
| 5474 | { | ||
| 5475 | 12027 | ulong n_parser_threads = 1; | |
| 5476 | |||
| 5477 |
2/2✓ Branch 0 taken 12027 times.
✓ Branch 1 taken 12027 times.
|
24054 | while (n_parser_threads < ddl::fts_parser_threads) { |
| 5478 | 12027 | n_parser_threads <<= 1; | |
| 5479 | } | ||
| 5480 | |||
| 5481 | 12027 | ddl::fts_parser_threads = n_parser_threads; | |
| 5482 | } | ||
| 5483 | |||
| 5484 | /* Store the default charset-collation number of this MySQL | ||
| 5485 | installation */ | ||
| 5486 | |||
| 5487 | 12027 | data_mysql_default_charset_coll = (ulint)default_charset_info->number; | |
| 5488 | |||
| 5489 | 12027 | innobase_commit_concurrency_init_default(); | |
| 5490 | |||
| 5491 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 12014 times.
|
12027 | if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { |
| 5492 | 13 | srv_read_only_mode = true; | |
| 5493 | } | ||
| 5494 | |||
| 5495 | 12027 | high_level_read_only = | |
| 5496 |
4/4✓ Branch 0 taken 11972 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 11967 times.
|
12027 | srv_read_only_mode || srv_force_recovery > SRV_FORCE_NO_TRX_UNDO; |
| 5497 | |||
| 5498 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 11972 times.
|
12027 | if (srv_read_only_mode) { |
| 5499 |
2/4✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
|
55 | ib::info(ER_IB_MSG_540) << "Started in read only mode"; |
| 5500 | |||
| 5501 | /* There is no write except to intrinsic table and so turn-off | ||
| 5502 | doublewrite mechanism completely. */ | ||
| 5503 | 55 | dblwr::g_mode = dblwr::Mode::OFF; | |
| 5504 | } | ||
| 5505 | |||
| 5506 | #ifdef LINUX_NATIVE_AIO | ||
| 5507 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | if (srv_use_native_aio) { |
| 5508 |
2/4✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12027 times.
✗ Branch 3 not taken.
|
12027 | ib::info(ER_IB_MSG_541) << "Using Linux native AIO"; |
| 5509 | } | ||
| 5510 | #elif !defined _WIN32 | ||
| 5511 | /* Currently native AIO is supported only on Windows and Linux | ||
| 5512 | and that also when the support is compiled in. In all other | ||
| 5513 | cases, we ignore the setting of innodb_use_native_aio. */ | ||
| 5514 | srv_use_native_aio = false; | ||
| 5515 | #endif | ||
| 5516 | |||
| 5517 | #ifndef _WIN32 | ||
| 5518 | /* Check if innodb_dedicated_server == ON and O_DIRECT is supported */ | ||
| 5519 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12027 times.
|
12027 | if (srv_dedicated_server && sysvar_source_svc != nullptr && |
| 5520 | ✗ | os_is_o_direct_supported()) { | |
| 5521 | static const char *variable_name = "innodb_flush_method"; | ||
| 5522 | enum enum_variable_source source; | ||
| 5523 | |||
| 5524 | ✗ | if (!sysvar_source_svc->get(variable_name, strlen(variable_name), | |
| 5525 | &source)) { | ||
| 5526 | /* If innodb_flush_method is not specified explicitly */ | ||
| 5527 | ✗ | if (source == COMPILED) { | |
| 5528 | ✗ | innodb_flush_method = static_cast<ulong>(SRV_UNIX_O_DIRECT_NO_FSYNC); | |
| 5529 | } else { | ||
| 5530 | ✗ | ib::warn(ER_IB_MSG_542) | |
| 5531 | << "Option innodb_dedicated_server" | ||
| 5532 | " is ignored for innodb_flush_method" | ||
| 5533 | ✗ | "because innodb_flush_method=" | |
| 5534 | ✗ | << innodb_flush_method_names[innodb_flush_method] | |
| 5535 | ✗ | << " is specified explicitly."; | |
| 5536 | } | ||
| 5537 | } | ||
| 5538 | } | ||
| 5539 | |||
| 5540 | 12027 | srv_unix_file_flush_method = | |
| 5541 | 12027 | static_cast<srv_unix_flush_t>(innodb_flush_method); | |
| 5542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | ut_ad(innodb_flush_method <= SRV_UNIX_O_DIRECT_NO_FSYNC); |
| 5543 | #else | ||
| 5544 | srv_win_file_flush_method = static_cast<srv_win_flush_t>(innodb_flush_method); | ||
| 5545 | ut_ad(innodb_flush_method <= SRV_WIN_IO_NORMAL); | ||
| 5546 | if (srv_use_native_aio) { | ||
| 5547 | ib::info(ER_IB_MSG_541) << "Using Windows native AIO"; | ||
| 5548 | } | ||
| 5549 | #endif /* !_WIN32 */ | ||
| 5550 | |||
| 5551 | /* Set the maximum number of threads which can wait for a semaphore | ||
| 5552 | inside InnoDB: this is the 'sync wait array' size, as well as the | ||
| 5553 | maximum number of threads that can wait in the 'srv_conc array' for | ||
| 5554 | their time to enter InnoDB. */ | ||
| 5555 | 12027 | srv_max_n_threads = 100 * 1024; | |
| 5556 | |||
| 5557 | /* This is the first time univ_page_size is used. | ||
| 5558 | It was initialized to 16k pages before srv_page_size was set */ | ||
| 5559 |
2/4✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12027 times.
✗ Branch 3 not taken.
|
12027 | univ_page_size.copy_from(page_size_t(srv_page_size, srv_page_size, false)); |
| 5560 | |||
| 5561 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | srv_sys_space.set_space_id(TRX_SYS_SPACE); |
| 5562 | |||
| 5563 | /* Create the filespace flags. */ | ||
| 5564 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | predefined_flags = fsp_flags_init(univ_page_size, false, false, true, false); |
| 5565 | 12027 | fsp_flags_set_sdi(predefined_flags); | |
| 5566 | |||
| 5567 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | srv_sys_space.set_flags(predefined_flags); |
| 5568 | |||
| 5569 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | srv_sys_space.set_name(dict_sys_t::s_sys_space_name); |
| 5570 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | srv_sys_space.set_path(srv_data_home); |
| 5571 | |||
| 5572 | /* We set the temporary tablspace id later, after recovery. | ||
| 5573 | The temp tablespace doesn't support raw devices. | ||
| 5574 | Set the name and path. */ | ||
| 5575 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | srv_tmp_space.set_name(dict_sys_t::s_temp_space_name); |
| 5576 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | srv_tmp_space.set_path(srv_data_home); |
| 5577 | |||
| 5578 | /* Create the filespace flags with the temp flag set. */ | ||
| 5579 | uint32_t fsp_flags = | ||
| 5580 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | fsp_flags_init(univ_page_size, false, false, false, true); |
| 5581 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | srv_tmp_space.set_flags(fsp_flags); |
| 5582 | |||
| 5583 | /* Set buffer pool size to default for fast startup when mysqld is | ||
| 5584 | run with --help --verbose options. */ | ||
| 5585 | 12027 | ulint srv_buf_pool_size_org = 0; | |
| 5586 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
12027 | if (opt_help && opt_verbose && opt_validate_config && |
| 5587 | ✗ | srv_buf_pool_size > srv_buf_pool_def_size) { | |
| 5588 | ✗ | ib::warn(ER_IB_MSG_543) << "Setting innodb_buf_pool_size to " | |
| 5589 | ✗ | << srv_buf_pool_def_size << " for fast startup, " | |
| 5590 | ✗ | << "when running with --help --verbose options."; | |
| 5591 | ✗ | srv_buf_pool_size_org = srv_buf_pool_size; | |
| 5592 | ✗ | srv_buf_pool_size = srv_buf_pool_def_size; | |
| 5593 | } | ||
| 5594 | |||
| 5595 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | innodb_buffer_pool_size_init(); |
| 5596 | |||
| 5597 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | innodb_undo_tablespaces_deprecate(); |
| 5598 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | innodb_parallel_doublewrite_path_deprecate(); |
| 5599 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | innodb_parallel_dblwr_encrypt_deprecate(); |
| 5600 | |||
| 5601 |
1/2✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
|
12027 | innodb_redo_log_capacity_init(); |
| 5602 | |||
| 5603 | /* Set the original value back to show in help. */ | ||
| 5604 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
|
12027 | if (srv_buf_pool_size_org != 0) { |
| 5605 | ✗ | srv_buf_pool_size_org = buf_pool_size_align(srv_buf_pool_size_org); | |
| 5606 | ✗ | srv_buf_pool_curr_size = srv_buf_pool_size_org; | |
| 5607 | } | ||
| 5608 | |||
| 5609 |
2/2✓ Branch 0 taken 12014 times.
✓ Branch 1 taken 13 times.
|
12027 | if (srv_n_page_cleaners > srv_buf_pool_instances) { |
| 5610 | /* limit of page_cleaner parallelizability | ||
| 5611 | is number of buffer pool instances. */ | ||
| 5612 | 12014 | srv_n_page_cleaners = srv_buf_pool_instances; | |
| 5613 | } | ||
| 5614 | |||
| 5615 | 12027 | srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE); | |
| 5616 | |||
| 5617 | 12027 | return 0; | |
| 5618 | 12035 | } | |
| 5619 | |||
| 5620 | 11994 | long innobase_get_open_files_limit() { return innobase_open_files; } | |
| 5621 | 12 | void innobase_set_open_files_limit(long new_limit) { | |
| 5622 | 12 | innobase_open_files = new_limit; | |
| 5623 | 12 | } | |
| 5624 | |||
| 5625 | /** Perform post-commit/rollback cleanup after DDL statement | ||
| 5626 | @param[in,out] thd connection thread */ | ||
| 5627 | 317739 | static void innobase_post_ddl(THD *thd) { | |
| 5628 | /* During upgrade, etc., the log_ddl may haven't been | ||
| 5629 | initialized and there is nothing to do now. */ | ||
| 5630 |
2/2✓ Branch 0 taken 304820 times.
✓ Branch 1 taken 12919 times.
|
317739 | if (log_ddl != nullptr) { |
| 5631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 304820 times.
|
304820 | DBUG_EXECUTE_IF("DDL_Log_remove_inject_startup_error_3", |
| 5632 | srv_inject_too_many_concurrent_trxs = true;); | ||
| 5633 | |||
| 5634 | 304820 | dberr_t err = log_ddl->post_ddl(thd); | |
| 5635 | |||
| 5636 | /* If this fails, do not continue startup. */ | ||
| 5637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 304718 times.
|
304718 | if (err != DB_SUCCESS) { |
| 5638 | ✗ | ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_DDL_LOG_FAIL_POST_DDL); | |
| 5639 | } | ||
| 5640 | } | ||
| 5641 | 317637 | } | |
| 5642 | |||
| 5643 | /** Initialize the InnoDB storage engine plugin. | ||
| 5644 | @param[in,out] p InnoDB handlerton | ||
| 5645 | @return error code | ||
| 5646 | @retval 0 on success */ | ||
| 5647 | 12035 | static int innodb_init(void *p) { | |
| 5648 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | DBUG_TRACE; |
| 5649 | |||
| 5650 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | acquire_plugin_services(); |
| 5651 | |||
| 5652 | 12035 | handlerton *innobase_hton = (handlerton *)p; | |
| 5653 | 12035 | innodb_hton_ptr = innobase_hton; | |
| 5654 | |||
| 5655 | 12035 | innobase_hton->state = SHOW_OPTION_YES; | |
| 5656 | 12035 | innobase_hton->db_type = DB_TYPE_INNODB; | |
| 5657 | 12035 | innobase_hton->savepoint_offset = sizeof(trx_named_savept_t); | |
| 5658 | 12035 | innobase_hton->close_connection = innobase_close_connection; | |
| 5659 | 12035 | innobase_hton->kill_connection = innobase_kill_connection; | |
| 5660 | 12035 | innobase_hton->savepoint_set = innobase_savepoint; | |
| 5661 | 12035 | innobase_hton->savepoint_rollback = innobase_rollback_to_savepoint; | |
| 5662 | |||
| 5663 | 12035 | innobase_hton->savepoint_rollback_can_release_mdl = | |
| 5664 | innobase_rollback_to_savepoint_can_release_mdl; | ||
| 5665 | |||
| 5666 | 12035 | innobase_hton->savepoint_release = innobase_release_savepoint; | |
| 5667 | 12035 | innobase_hton->commit = innobase_commit; | |
| 5668 | 12035 | innobase_hton->rollback = innobase_rollback; | |
| 5669 | 12035 | innobase_hton->prepare = innobase_xa_prepare; | |
| 5670 | 12035 | innobase_hton->recover = innobase_xa_recover; | |
| 5671 | 12035 | innobase_hton->recover_prepared_in_tc = innobase_xa_recover_prepared_in_tc; | |
| 5672 | 12035 | innobase_hton->commit_by_xid = innobase_commit_by_xid; | |
| 5673 | 12035 | innobase_hton->rollback_by_xid = innobase_rollback_by_xid; | |
| 5674 | 12035 | innobase_hton->set_prepared_in_tc = innobase_set_prepared_in_tc; | |
| 5675 | 12035 | innobase_hton->set_prepared_in_tc_by_xid = innobase_set_prepared_in_tc_by_xid; | |
| 5676 | 12035 | innobase_hton->create = innobase_create_handler; | |
| 5677 | 12035 | innobase_hton->is_valid_tablespace_name = innobase_is_valid_tablespace_name; | |
| 5678 | 12035 | innobase_hton->alter_tablespace = innobase_alter_tablespace; | |
| 5679 | 12035 | innobase_hton->get_tablespace_filename_ext = | |
| 5680 | innobase_get_tablespace_filename_ext; | ||
| 5681 | 12035 | innobase_hton->upgrade_tablespace = dd_upgrade_tablespace; | |
| 5682 | 12035 | innobase_hton->upgrade_space_version = upgrade_space_version; | |
| 5683 | 12035 | innobase_hton->upgrade_logs = dd_upgrade_logs; | |
| 5684 | 12035 | innobase_hton->finish_upgrade = dd_upgrade_finish; | |
| 5685 | 12035 | innobase_hton->pre_dd_shutdown = innodb_pre_dd_shutdown; | |
| 5686 | 12035 | innobase_hton->panic = innodb_shutdown; | |
| 5687 | 12035 | innobase_hton->partition_flags = innobase_partition_flags; | |
| 5688 | |||
| 5689 | 12035 | innobase_hton->start_consistent_snapshot = | |
| 5690 | innobase_start_trx_and_assign_read_view; | ||
| 5691 | 12035 | innobase_hton->clone_consistent_snapshot = | |
| 5692 | innobase_start_trx_and_clone_read_view; | ||
| 5693 | |||
| 5694 | 12035 | innobase_hton->store_binlog_info = innobase_store_binlog_info; | |
| 5695 | |||
| 5696 | 12035 | innobase_hton->flush_logs = innobase_flush_logs; | |
| 5697 | 12035 | innobase_hton->show_status = innobase_show_status; | |
| 5698 | 12035 | innobase_hton->lock_hton_log = innobase_lock_hton_log; | |
| 5699 | 12035 | innobase_hton->unlock_hton_log = innobase_unlock_hton_log; | |
| 5700 | 12035 | innobase_hton->collect_hton_log_info = innobase_collect_hton_log_info; | |
| 5701 | 12035 | innobase_hton->fill_is_table = innobase_fill_i_s_table; | |
| 5702 | 12035 | innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS | | |
| 5703 | HTON_SUPPORTS_FOREIGN_KEYS | HTON_SUPPORTS_ATOMIC_DDL | | ||
| 5704 | HTON_CAN_RECREATE | HTON_SUPPORTS_SECONDARY_ENGINE | | ||
| 5705 | HTON_SUPPORTS_TABLE_ENCRYPTION | | ||
| 5706 | HTON_SUPPORTS_ONLINE_BACKUPS | HTON_SUPPORTS_COMPRESSED_COLUMNS | | ||
| 5707 | HTON_SUPPORTS_GENERATED_INVISIBLE_PK; | ||
| 5708 | |||
| 5709 | 12035 | innobase_hton->replace_native_transaction_in_thd = innodb_replace_trx_in_thd; | |
| 5710 | 12035 | innobase_hton->file_extensions = ha_innobase_exts; | |
| 5711 | 12035 | innobase_hton->data = &innodb_api_cb; | |
| 5712 | 12035 | innobase_hton->ddse_dict_init = innobase_ddse_dict_init; | |
| 5713 | |||
| 5714 | 12035 | innobase_hton->dict_register_dd_table_id = innobase_dict_register_dd_table_id; | |
| 5715 | |||
| 5716 | 12035 | innobase_hton->dict_cache_reset = innobase_dict_cache_reset; | |
| 5717 | 12035 | innobase_hton->dict_cache_reset_tables_and_tablespaces = | |
| 5718 | innobase_dict_cache_reset_tables_and_tablespaces; | ||
| 5719 | |||
| 5720 | 12035 | innobase_hton->dict_recover = innobase_dict_recover; | |
| 5721 | 12035 | innobase_hton->dict_get_server_version = innobase_dict_get_server_version; | |
| 5722 | 12035 | innobase_hton->dict_set_server_version = innobase_dict_set_server_version; | |
| 5723 | |||
| 5724 | 12035 | innobase_hton->post_recover = innobase_post_recover; | |
| 5725 | |||
| 5726 | 12035 | innobase_hton->is_supported_system_table = innobase_is_supported_system_table; | |
| 5727 | |||
| 5728 | 12035 | innobase_hton->get_table_statistics = innobase_get_table_statistics; | |
| 5729 | |||
| 5730 | 12035 | innobase_hton->get_index_column_cardinality = | |
| 5731 | innobase_get_index_column_cardinality; | ||
| 5732 | |||
| 5733 | 12035 | innobase_hton->get_tablespace_statistics = innobase_get_tablespace_statistics; | |
| 5734 | 12035 | innobase_hton->get_tablespace_type = innobase_get_tablespace_type; | |
| 5735 | 12035 | innobase_hton->get_tablespace_type_by_name = | |
| 5736 | innobase_get_tablespace_type_by_name; | ||
| 5737 | |||
| 5738 | 12035 | innobase_hton->is_tablespace_keyring_pre_v3_encrypted = | |
| 5739 | innobase_is_tablespace_keyring_pre_v3_encrypted; | ||
| 5740 | |||
| 5741 | 12035 | innobase_hton->is_dict_readonly = innobase_is_dict_readonly; | |
| 5742 | |||
| 5743 | 12035 | innobase_hton->sdi_create = dict_sdi_create; | |
| 5744 | 12035 | innobase_hton->sdi_drop = dict_sdi_drop; | |
| 5745 | 12035 | innobase_hton->sdi_get_keys = dict_sdi_get_keys; | |
| 5746 | 12035 | innobase_hton->sdi_get = dict_sdi_get; | |
| 5747 | 12035 | innobase_hton->sdi_set = dict_sdi_set; | |
| 5748 | 12035 | innobase_hton->sdi_delete = dict_sdi_delete; | |
| 5749 | |||
| 5750 | 12035 | innobase_hton->rotate_encryption_master_key = | |
| 5751 | innobase_encryption_key_rotation; | ||
| 5752 | |||
| 5753 | 12035 | innobase_hton->fix_tablespaces_empty_uuid = | |
| 5754 | innobase_fix_tablespaces_empty_uuid; | ||
| 5755 | |||
| 5756 | 12035 | innobase_hton->fix_default_table_encryption = | |
| 5757 | innobase_fix_default_table_encryption; | ||
| 5758 | |||
| 5759 | 12035 | innobase_hton->redo_log_set_state = innobase_redo_set_state; | |
| 5760 | |||
| 5761 | 12035 | innobase_hton->post_ddl = innobase_post_ddl; | |
| 5762 | |||
| 5763 | /* Initialize handler clone interfaces for. */ | ||
| 5764 | |||
| 5765 | 12035 | innobase_hton->clone_interface.clone_capability = innodb_clone_get_capability; | |
| 5766 | 12035 | innobase_hton->clone_interface.clone_begin = innodb_clone_begin; | |
| 5767 | 12035 | innobase_hton->clone_interface.clone_copy = innodb_clone_copy; | |
| 5768 | 12035 | innobase_hton->clone_interface.clone_ack = innodb_clone_ack; | |
| 5769 | 12035 | innobase_hton->clone_interface.clone_end = innodb_clone_end; | |
| 5770 | |||
| 5771 | 12035 | innobase_hton->clone_interface.clone_apply_begin = innodb_clone_apply_begin; | |
| 5772 | 12035 | innobase_hton->clone_interface.clone_apply = innodb_clone_apply; | |
| 5773 | 12035 | innobase_hton->clone_interface.clone_apply_end = innodb_clone_apply_end; | |
| 5774 | |||
| 5775 | 12035 | innobase_hton->foreign_keys_flags = | |
| 5776 | HTON_FKS_WITH_PREFIX_PARENT_KEYS | | ||
| 5777 | HTON_FKS_NEED_DIFFERENT_PARENT_AND_SUPPORTING_KEYS | | ||
| 5778 | HTON_FKS_WITH_EXTENDED_PARENT_KEYS; | ||
| 5779 | |||
| 5780 | 12035 | innobase_hton->check_fk_column_compat = innodb_check_fk_column_compat; | |
| 5781 | 12035 | innobase_hton->fk_name_suffix = {STRING_WITH_LEN("_ibfk_")}; | |
| 5782 | |||
| 5783 | 12035 | innobase_hton->is_reserved_db_name = innobase_check_reserved_file_name; | |
| 5784 | |||
| 5785 | 12035 | innobase_hton->page_track.start = innobase_page_track_start; | |
| 5786 | 12035 | innobase_hton->page_track.stop = innobase_page_track_stop; | |
| 5787 | 12035 | innobase_hton->page_track.purge = innobase_page_track_purge; | |
| 5788 | 12035 | innobase_hton->page_track.get_page_ids = innobase_page_track_get_page_ids; | |
| 5789 | 12035 | innobase_hton->page_track.get_num_page_ids = | |
| 5790 | innobase_page_track_get_num_page_ids; | ||
| 5791 | 12035 | innobase_hton->page_track.get_status = innobase_page_track_get_status; | |
| 5792 | |||
| 5793 | 12035 | innobase_hton->upgrade_get_compression_dict_data = | |
| 5794 | dd_upgrade_get_compression_dict_data; | ||
| 5795 | |||
| 5796 | static_assert(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); | ||
| 5797 | |||
| 5798 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | os_file_set_umask(my_umask); |
| 5799 | |||
| 5800 | /* Setup the memory alloc/free tracing mechanisms before calling | ||
| 5801 | any functions that could possibly allocate memory. */ | ||
| 5802 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | ut_new_boot(); |
| 5803 | |||
| 5804 | #ifdef HAVE_PSI_INTERFACE | ||
| 5805 | /* Register keys with MySQL performance schema */ | ||
| 5806 | int count; | ||
| 5807 | |||
| 5808 | #ifdef UNIV_DEBUG | ||
| 5809 | /** Count of Performance Schema keys that have been registered. */ | ||
| 5810 | 12035 | int global_count = 0; | |
| 5811 | #endif /* UNIV_DEBUG */ | ||
| 5812 | |||
| 5813 | 12035 | count = static_cast<int>(array_elements(all_pthread_mutexes)); | |
| 5814 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_mutex_register("innodb", all_pthread_mutexes, count); |
| 5815 | |||
| 5816 | #ifdef UNIV_DEBUG | ||
| 5817 | 12035 | global_count += count; | |
| 5818 | #endif /* UNIV_DEBUG */ | ||
| 5819 | |||
| 5820 | #ifdef UNIV_PFS_MEMORY | ||
| 5821 | 12035 | count = static_cast<int>(array_elements(pfs_instrumented_innodb_memory)); | |
| 5822 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_memory_register("innodb", pfs_instrumented_innodb_memory, count); |
| 5823 | #endif /* UNIV_PFS_MEMORY */ | ||
| 5824 | |||
| 5825 | #ifdef UNIV_PFS_MUTEX | ||
| 5826 | 12035 | count = static_cast<int>(array_elements(all_innodb_mutexes)); | |
| 5827 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_mutex_register("innodb", all_innodb_mutexes, count); |
| 5828 | |||
| 5829 | #ifdef UNIV_DEBUG | ||
| 5830 | 12035 | global_count += count; | |
| 5831 | #endif /* UNIV_DEBUG */ | ||
| 5832 | |||
| 5833 | #endif /* UNIV_PFS_MUTEX */ | ||
| 5834 | |||
| 5835 | #ifdef UNIV_PFS_RWLOCK | ||
| 5836 | 12035 | count = static_cast<int>(array_elements(all_innodb_rwlocks)); | |
| 5837 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_rwlock_register("innodb", all_innodb_rwlocks, count); |
| 5838 | |||
| 5839 | #ifdef UNIV_DEBUG | ||
| 5840 | 12035 | global_count += count; | |
| 5841 | #endif /* UNIV_DEBUG */ | ||
| 5842 | |||
| 5843 | #endif /* UNIV_PFS_MUTEX */ | ||
| 5844 | |||
| 5845 | #ifdef UNIV_PFS_THREAD | ||
| 5846 | 12035 | count = static_cast<int>(array_elements(all_innodb_threads)); | |
| 5847 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_thread_register("innodb", all_innodb_threads, count); |
| 5848 | |||
| 5849 | #ifdef UNIV_DEBUG | ||
| 5850 | 12035 | global_count += count; | |
| 5851 | #endif /* UNIV_DEBUG */ | ||
| 5852 | |||
| 5853 | #endif /* UNIV_PFS_THREAD */ | ||
| 5854 | |||
| 5855 | #ifdef UNIV_PFS_IO | ||
| 5856 | 12035 | count = static_cast<int>(array_elements(all_innodb_files)); | |
| 5857 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_file_register("innodb", all_innodb_files, count); |
| 5858 | |||
| 5859 | #ifdef UNIV_DEBUG | ||
| 5860 | 12035 | global_count += count; | |
| 5861 | #endif /* UNIV_DEBUG */ | ||
| 5862 | |||
| 5863 | #endif /* UNIV_PFS_IO */ | ||
| 5864 | |||
| 5865 | 12035 | count = static_cast<int>(array_elements(all_innodb_conds)); | |
| 5866 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_cond_register("innodb", all_innodb_conds, count); |
| 5867 | |||
| 5868 | #ifdef UNIV_DEBUG | ||
| 5869 | 12035 | global_count += count; | |
| 5870 | #endif /* UNIV_DEBUG */ | ||
| 5871 | |||
| 5872 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | mysql_data_lock_register(&innodb_data_lock_inspector); |
| 5873 | |||
| 5874 | #ifdef UNIV_DEBUG | ||
| 5875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12035 times.
|
12035 | if (mysql_pfs_key_t::get_count() != global_count) { |
| 5876 | ✗ | ib::error(ER_IB_MSG_544) << "You have created new InnoDB PFS key(s) but " | |
| 5877 | ✗ | << mysql_pfs_key_t::get_count() - global_count | |
| 5878 | ✗ | << " key(s) is/are not registered with PFS. Please" | |
| 5879 | ✗ | << " register the keys in PFS arrays in" | |
| 5880 | ✗ | << " ha_innodb.cc."; | |
| 5881 | |||
| 5882 | ✗ | return HA_ERR_INITIALIZATION; | |
| 5883 | } | ||
| 5884 | #endif /* UNIV_DEBUG */ | ||
| 5885 | |||
| 5886 | #endif /* HAVE_PSI_INTERFACE */ | ||
| 5887 | |||
| 5888 |
1/2✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
|
12035 | os_event_global_init(); |
| 5889 | |||
| 5890 |
3/4✓ Branch 0 taken 12035 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 12027 times.
|
12035 | if (innodb_init_params()) { |
| 5891 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | return innodb_init_abort(); |
| 5892 | } | ||
| 5893 | |||
| 5894 | /* After this point, error handling has to use | ||
| 5895 | innodb_init_abort(). */ | ||
| 5896 | |||
| 5897 | /* Initialize component service handles */ | ||
| 5898 |
2/4✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
|
12027 | if (innobase::component_services::intitialize_service_handles() == false) { |
| 5899 | ✗ | return innodb_init_abort(); | |
| 5900 | } | ||
| 5901 | |||
| 5902 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 12027 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
|
12027 | if (srv_default_table_encryption == DEFAULT_TABLE_ENC_ONLINE_TO_KEYRING && |
| 5903 | ✗ | !Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist( | |
| 5904 | FIL_DEFAULT_ENCRYPTION_KEY, server_uuid)) { | ||
| 5905 | ✗ | sql_print_error( | |
| 5906 | "InnoDB: cannot enable encryption, innodb_encrypt_tables is set to " | ||
| 5907 | "value different than OFF, but " | ||
| 5908 | "keyring plugin is not available"); | ||
| 5909 | ✗ | return innodb_init_abort(); | |
| 5910 | } | ||
| 5911 | |||
| 5912 | // We are starting encryption threads, we must lock the keyring plugins | ||
| 5913 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12025 times.
|
12027 | if (srv_n_fil_crypt_threads_requested > 0) { |
| 5914 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | uint number_of_keyring_locked = lock_keyrings(nullptr); |
| 5915 | |||
| 5916 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (number_of_keyring_locked == 0) { |
| 5917 | ✗ | sql_print_error( | |
| 5918 | "InnoDB: cannot enable encryption threads, " | ||
| 5919 | "keyring plugin is not available"); | ||
| 5920 | |||
| 5921 | ✗ | return innodb_init_abort(); | |
| 5922 | } | ||
| 5923 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (Encryption::is_keyring_alive() == false) { |
| 5924 | ✗ | sql_print_error( | |
| 5925 | "InnoDB: keyring plugin is installed but it seems it was not " | ||
| 5926 | "properly initialized. Cannot enable encryption threads."); | ||
| 5927 | ✗ | unlock_keyrings(nullptr); | |
| 5928 | |||
| 5929 | ✗ | return innodb_init_abort(); | |
| 5930 | } | ||
| 5931 | } | ||
| 5932 | |||
| 5933 |
2/4✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12027 times.
|
12027 | if (!srv_sys_space.parse_params(innobase_data_file_path, true)) { |
| 5934 | ✗ | ib::error(ER_IB_MSG_545) | |
| 5935 | ✗ | << "Unable to parse innodb_data_file_path=" << innobase_data_file_path; | |
| 5936 | ✗ | return innodb_init_abort(); | |
| 5937 | } | ||
| 5938 | |||
| 5939 |
3/4✓ Branch 0 taken 12027 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12024 times.
|
12027 | if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) { |
| 5940 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | ib::error(ER_IB_MSG_546) << "Unable to parse innodb_temp_data_file_path=" |
| 5941 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | << innobase_temp_data_file_path; |
| 5942 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | return innodb_init_abort(); |
| 5943 | } | ||
| 5944 | |||
| 5945 | /* Perform all sanity check before we take action of deleting files*/ | ||
| 5946 |
3/4✓ Branch 0 taken 12024 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12023 times.
|
12024 | if (srv_sys_space.intersection(&srv_tmp_space)) { |
| 5947 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | log_errlog(ERROR_LEVEL, ER_INNODB_FILES_SAME, srv_tmp_space.name(), |
| 5948 | srv_sys_space.name()); | ||
| 5949 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return innodb_init_abort(); |
| 5950 | } | ||
| 5951 | |||
| 5952 | /* Check for keyring plugin if UNDO/REDO logs are intended to be encrypted */ | ||
| 5953 |
6/6✓ Branch 0 taken 11993 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 11961 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 12018 times.
|
12085 | if ((srv_undo_log_encrypt || srv_redo_log_encrypt) && |
| 5954 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 57 times.
|
62 | Encryption::check_keyring() == false) { |
| 5955 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | return innodb_init_abort(); |
| 5956 | } | ||
| 5957 | |||
| 5958 | 12018 | return 0; | |
| 5959 | 12035 | } | |
| 5960 | |||
| 5961 | /** De initialize the InnoDB storage engine plugin. */ | ||
| 5962 | 10400 | static int innodb_deinit(MYSQL_PLUGIN plugin_info [[maybe_unused]]) { | |
| 5963 | 10400 | release_plugin_services(); | |
| 5964 | 10400 | return 0; | |
| 5965 | } | ||
| 5966 | |||
| 5967 | /** Create a hard-coded tablespace file at server initialization. | ||
| 5968 | @param[in] space_id fil_space_t::id | ||
| 5969 | @param[in] filename file name | ||
| 5970 | @param[in] flags tabelspace flags | ||
| 5971 | @retval false on success | ||
| 5972 | @retval true on failure */ | ||
| 5973 | 380 | static bool dd_create_hardcoded(space_id_t space_id, const char *filename, | |
| 5974 | ulint flags) { | ||
| 5975 | 380 | page_no_t pages = FIL_IBD_FILE_INITIAL_SIZE; | |
| 5976 | |||
| 5977 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | dberr_t err = fil_ibd_create(space_id, dict_sys_t::s_dd_space_name, filename, |
| 5978 | flags, pages, FIL_ENCRYPTION_DEFAULT, | ||
| 5979 | 380 | KeyringEncryptionKeyIdInfo()); | |
| 5980 | |||
| 5981 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | if (err == DB_SUCCESS) { |
| 5982 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | mtr_t mtr; |
| 5983 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | mtr.start(); |
| 5984 | |||
| 5985 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | bool ret = fsp_header_init(space_id, pages, &mtr); |
| 5986 | |||
| 5987 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | mtr.commit(); |
| 5988 | |||
| 5989 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | if (ret) { |
| 5990 |
1/2✓ Branch 0 taken 380 times.
✗ Branch 1 not taken.
|
380 | btr_sdi_create_index(space_id, false); |
| 5991 | 380 | return (false); | |
| 5992 | } | ||
| 5993 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
|
380 | } |
| 5994 | |||
| 5995 | ✗ | return (true); | |
| 5996 | } | ||
| 5997 | |||
| 5998 | /** Open a hard-coded tablespace file at server initialization. | ||
| 5999 | @param[in] space_id fil_space_t::id | ||
| 6000 | @param[in] filename file name | ||
| 6001 | @param[in] flags tabelspace flags | ||
| 6002 | @retval false on success | ||
| 6003 | @retval true on failure */ | ||
| 6004 | 11540 | static bool dd_open_hardcoded(space_id_t space_id, const char *filename, | |
| 6005 | ulint flags) { | ||
| 6006 | 11540 | bool fail = false; | |
| 6007 |
1/2✓ Branch 0 taken 11540 times.
✗ Branch 1 not taken.
|
11540 | fil_space_t *space = fil_space_acquire_silent(space_id); |
| 6008 | 11540 | Keyring_encryption_info keyring_encryption_info; | |
| 6009 | |||
| 6010 |
2/2✓ Branch 0 taken 1979 times.
✓ Branch 1 taken 9561 times.
|
11540 | if (space != nullptr) { |
| 6011 | /* ADD SDI flag presence in predefined flags of mysql | ||
| 6012 | tablespace. */ | ||
| 6013 | |||
| 6014 |
2/4✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1979 times.
✗ Branch 3 not taken.
|
3958 | if (strstr(space->files.front().name, filename) != nullptr && |
| 6015 | /* Ignore encryption flag as it might have changed */ | ||
| 6016 |
1/2✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
|
1979 | !((space->flags ^ flags) & ~(FSP_FLAGS_MASK_ENCRYPTION))) { |
| 6017 |
1/2✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
|
1979 | fil_space_open_if_needed(space); |
| 6018 | |||
| 6019 | } else { | ||
| 6020 | ✗ | fail = true; | |
| 6021 | } | ||
| 6022 | |||
| 6023 |
1/2✓ Branch 0 taken 1979 times.
✗ Branch 1 not taken.
|
1979 | fil_space_release(space); |
| 6024 | |||
| 6025 |
1/2✓ Branch 0 taken 9561 times.
✗ Branch 1 not taken.
|
9561 | } else if (fil_ibd_open(true, FIL_TYPE_TABLESPACE, space_id, flags, |
| 6026 | dict_sys_t::s_dd_space_name, filename, true, | ||
| 6027 |
1/2✓ Branch 0 taken 9561 times.
✗ Branch 1 not taken.
|
9561 | false, keyring_encryption_info) == DB_SUCCESS) { |
| 6028 | /* Set fil_space_t::size, which is 0 initially. */ | ||
| 6029 |
1/2✓ Branch 0 taken 9561 times.
✗ Branch 1 not taken.
|
9561 | ulint size = fil_space_get_size(space_id); |
| 6030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9561 times.
|
9561 | ut_a(size != ULINT_UNDEFINED); |
| 6031 | |||
| 6032 | } else { | ||
| 6033 | ✗ | fail = true; | |
| 6034 | } | ||
| 6035 | |||
| 6036 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11540 times.
|
11540 | if (fail) { |
| 6037 | ✗ | my_error(ER_CANT_OPEN_FILE, MYF(0), filename, 0, ""); | |
| 6038 | } | ||
| 6039 | |||
| 6040 | 11540 | return (fail); | |
| 6041 | } | ||
| 6042 | |||
| 6043 | /** Open or create InnoDB data files. | ||
| 6044 | @param[in] dict_init_mode whether to create or open the files | ||
| 6045 | @param[in,out] tablespaces predefined tablespaces created by the DDSE | ||
| 6046 | @return 0 on success, 1 on failure */ | ||
| 6047 | 12008 | static int innobase_init_files(dict_init_mode_t dict_init_mode, | |
| 6048 | List<const Plugin_tablespace> *tablespaces, | ||
| 6049 | bool &is_dd_encrypted) { | ||
| 6050 |
1/2✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
|
12008 | DBUG_TRACE; |
| 6051 | |||
| 6052 |
6/8✓ Branch 0 taken 11715 times.
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 118 times.
✓ Branch 3 taken 11597 times.
✓ Branch 4 taken 118 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12008 times.
|
12008 | ut_ad(dict_init_mode == DICT_INIT_CREATE_FILES || |
| 6053 | dict_init_mode == DICT_INIT_CHECK_FILES || | ||
| 6054 | dict_init_mode == DICT_INIT_UPGRADE_57_FILES); | ||
| 6055 | |||
| 6056 | 12008 | bool create = (dict_init_mode == DICT_INIT_CREATE_FILES); | |
| 6057 | |||
| 6058 | /* Check if the data files exist or not. */ | ||
| 6059 | dberr_t err = | ||
| 6060 |
1/2✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
|
12008 | srv_sys_space.check_file_spec(create, MIN_EXPECTED_TABLESPACE_SIZE); |
| 6061 | |||
| 6062 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12005 times.
|
12008 | if (err != DB_SUCCESS) { |
| 6063 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | return innodb_init_abort(); |
| 6064 | } | ||
| 6065 | |||
| 6066 | 12005 | srv_is_upgrade_mode = (dict_init_mode == DICT_INIT_UPGRADE_57_FILES); | |
| 6067 | |||
| 6068 | /* Start the InnoDB server. */ | ||
| 6069 |
1/2✓ Branch 0 taken 12004 times.
✗ Branch 1 not taken.
|
12005 | err = srv_start(create); |
| 6070 | |||
| 6071 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 11920 times.
|
12004 | if (err != DB_SUCCESS) { |
| 6072 |
1/2✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
|
84 | return innodb_init_abort(); |
| 6073 | } | ||
| 6074 | |||
| 6075 | 11920 | space_id_t upgrade_mysql_plugin_space = SPACE_UNKNOWN; | |
| 6076 | |||
| 6077 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 11830 times.
|
11920 | if (srv_is_upgrade_mode) { |
| 6078 |
2/4✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
|
90 | if (!dict_sys_table_id_build()) { |
| 6079 | ✗ | return innodb_init_abort(); | |
| 6080 | } | ||
| 6081 | |||
| 6082 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (trx_sys->found_prepared_trx) { |
| 6083 | ✗ | ib::error(ER_DD_UPGRADE_FOUND_PREPARED_XA_TRANSACTION); | |
| 6084 | ✗ | return innodb_init_abort(); | |
| 6085 | } | ||
| 6086 | |||
| 6087 | /* Disable AHI when we start loading tables for purge. | ||
| 6088 | These tables are evicted anyway after purge. */ | ||
| 6089 | |||
| 6090 | 90 | bool old_btr_search_value = btr_search_enabled; | |
| 6091 | 90 | btr_search_enabled = false; | |
| 6092 | |||
| 6093 | /* Load all tablespaces upfront from InnoDB Dictionary. | ||
| 6094 | This is needed for applying purge and ibuf from 5.7 */ | ||
| 6095 |
2/4✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
|
90 | if (dict_load_tablespaces_for_upgrade()) { |
| 6096 | // there is a keyring v1 encrypted table - fail the upgrade | ||
| 6097 | ✗ | ib::error(ER_UPGRADE_KEYRING_UNSUPPORTED_VERSION_ENCRYPTION); | |
| 6098 | ✗ | return innodb_init_abort(); | |
| 6099 | } | ||
| 6100 | |||
| 6101 | /* Start purge threads immediately and wait for purge to | ||
| 6102 | become empty. All table_ids will be adjusted by a fixed | ||
| 6103 | offset during upgrade. So purge cannot load a table by | ||
| 6104 | table_id later. Also InnoDB dictionary will be dropped | ||
| 6105 | during the process of upgrade. So apply all the purge | ||
| 6106 | now. */ | ||
| 6107 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | srv_start_purge_threads(); |
| 6108 | |||
| 6109 | uint64_t rseg_history_len; | ||
| 6110 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 90 times.
|
188 | while ((rseg_history_len = trx_sys->rseg_history_len.load()) != 0) { |
| 6111 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | ib::info(ER_IB_MSG_547) |
| 6112 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | << "Waiting for purge to become empty:" |
| 6113 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | << " current purge history len is " << rseg_history_len; |
| 6114 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | sleep(1); |
| 6115 | } | ||
| 6116 | |||
| 6117 | 90 | srv_upgrade_old_undo_found = false; | |
| 6118 | |||
| 6119 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | buf_flush_sync_all_buf_pools(); |
| 6120 | |||
| 6121 | /* We have to find the space_id of "mysql/plugin" here. i.e. before we evict | ||
| 6122 | the tables from cache. */ | ||
| 6123 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | dict_table_t *table = dict_table_open_on_name("mysql/plugin", false, true, |
| 6124 | DICT_ERR_IGNORE_NONE); | ||
| 6125 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | if (table != nullptr) { |
| 6126 | 90 | upgrade_mysql_plugin_space = table->space; | |
| 6127 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | dict_table_close(table, false, false); |
| 6128 | } | ||
| 6129 | |||
| 6130 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | dict_upgrade_evict_tables_cache(); |
| 6131 | |||
| 6132 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | dict_stats_evict_tablespaces(); |
| 6133 | |||
| 6134 | 90 | btr_search_enabled = old_btr_search_value; | |
| 6135 | } | ||
| 6136 | |||
| 6137 | 11920 | bool do_encrypt = false; | |
| 6138 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | bool ret = dict_detect_encryption_of_mysql_ibd( |
| 6139 | dict_init_mode, upgrade_mysql_plugin_space, do_encrypt); | ||
| 6140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11920 times.
|
11920 | if (!ret) { |
| 6141 | ✗ | ib::error(ER_XB_MSG_4, "mysql.ibd") | |
| 6142 | << "Failed to determine if mysql.ibd is encrypted. " | ||
| 6143 | ✗ | "Have you deleted it?"; | |
| 6144 | ✗ | return innodb_init_abort(); | |
| 6145 | } | ||
| 6146 | |||
| 6147 |
4/6✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 51 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11920 times.
|
11920 | if (do_encrypt && !Encryption::check_keyring()) { |
| 6148 | ✗ | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); | |
| 6149 | ✗ | return innodb_init_abort(); | |
| 6150 | } | ||
| 6151 | |||
| 6152 | 11920 | is_dd_encrypted = do_encrypt; | |
| 6153 | |||
| 6154 | 11920 | const ulint dd_space_flags = | |
| 6155 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
|
11920 | do_encrypt ? predefined_flags | FSP_FLAGS_MASK_ENCRYPTION |
| 6156 | : predefined_flags; | ||
| 6157 | |||
| 6158 | // For upgrade from 5.7, create mysql.ibd | ||
| 6159 | 11920 | create |= (dict_init_mode == DICT_INIT_UPGRADE_57_FILES); | |
| 6160 |
3/4✓ Branch 0 taken 380 times.
✓ Branch 1 taken 11540 times.
✓ Branch 2 taken 380 times.
✗ Branch 3 not taken.
|
11920 | ret = create ? dd_create_hardcoded(dict_sys_t::s_dict_space_id, |
| 6161 | dict_sys_t::s_dd_space_file_name, | ||
| 6162 | dd_space_flags) | ||
| 6163 |
1/2✓ Branch 0 taken 11540 times.
✗ Branch 1 not taken.
|
11540 | : dd_open_hardcoded(dict_sys_t::s_dict_space_id, |
| 6164 | dict_sys_t::s_dd_space_file_name, | ||
| 6165 | dd_space_flags); | ||
| 6166 | |||
| 6167 | /* Once hardcoded tablespace mysql is created or opened, | ||
| 6168 | prepare it along with innodb system tablespace for server. | ||
| 6169 | Tell server that these two hardcoded tablespaces exist. */ | ||
| 6170 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | if (!ret) { |
| 6171 | 11920 | const size_t len = | |
| 6172 | 30 + sizeof("id=;flags=;server_version=;space_version=;state=normal"); | ||
| 6173 | 11920 | const char *fmt = | |
| 6174 | "id=%u;flags=%u;server_version=%u;space_version=%u;state=normal"; | ||
| 6175 | static char se_private_data_innodb_system[len]; | ||
| 6176 | static char se_private_data_dd[len]; | ||
| 6177 | 11920 | snprintf(se_private_data_innodb_system, len, fmt, TRX_SYS_SPACE, | |
| 6178 | srv_sys_space.flags(), DD_SPACE_CURRENT_SRV_VERSION, | ||
| 6179 | DD_SPACE_CURRENT_SPACE_VERSION); | ||
| 6180 | |||
| 6181 | 11920 | snprintf(se_private_data_dd, len, fmt, dict_sys_t::s_dict_space_id, | |
| 6182 | dd_space_flags, DD_SPACE_CURRENT_SRV_VERSION, | ||
| 6183 | DD_SPACE_CURRENT_SPACE_VERSION); | ||
| 6184 | |||
| 6185 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
|
11920 | const char *dd_space_options = do_encrypt ? "encryption=y" : ""; |
| 6186 | |||
| 6187 | static Plugin_tablespace dd_space(dict_sys_t::s_dd_space_name, | ||
| 6188 | dd_space_options, se_private_data_dd, "", | ||
| 6189 |
3/8✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
11920 | innobase_hton_name); |
| 6190 | static Plugin_tablespace::Plugin_tablespace_file dd_file( | ||
| 6191 |
2/4✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
|
11920 | dict_sys_t::s_dd_space_file_name, ""); |
| 6192 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | dd_space.add_file(&dd_file); |
| 6193 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | tablespaces->push_back(&dd_space); |
| 6194 | |||
| 6195 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 11916 times.
|
11920 | const char *options = srv_sys_space.is_encrypted() ? "encryption=y" : ""; |
| 6196 | |||
| 6197 | static Plugin_tablespace innodb(dict_sys_t::s_sys_space_name, options, | ||
| 6198 | se_private_data_innodb_system, "", | ||
| 6199 |
3/8✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
11920 | innobase_hton_name); |
| 6200 | 11920 | Tablespace::files_t::const_iterator end = srv_sys_space.m_files.end(); | |
| 6201 | 11920 | Tablespace::files_t::const_iterator begin = srv_sys_space.m_files.begin(); | |
| 6202 |
2/2✓ Branch 0 taken 11944 times.
✓ Branch 1 taken 11920 times.
|
23864 | for (Tablespace::files_t::const_iterator it = begin; it != end; ++it) { |
| 6203 | 11944 | innobase_sys_files.push_back( | |
| 6204 |
2/4✓ Branch 0 taken 11944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11944 times.
✗ Branch 3 not taken.
|
11944 | ut::new_withkey<Plugin_tablespace::Plugin_tablespace_file>( |
| 6205 | 11944 | UT_NEW_THIS_FILE_PSI_KEY, it->name(), "")); | |
| 6206 |
1/2✓ Branch 0 taken 11944 times.
✗ Branch 1 not taken.
|
11944 | innodb.add_file(innobase_sys_files.back()); |
| 6207 | } | ||
| 6208 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | tablespaces->push_back(&innodb); |
| 6209 | |||
| 6210 | } else { | ||
| 6211 | ✗ | return innodb_init_abort(); | |
| 6212 | } | ||
| 6213 | |||
| 6214 | 11920 | innobase_old_blocks_pct = static_cast<uint>( | |
| 6215 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | buf_LRU_old_ratio_update(innobase_old_blocks_pct, true)); |
| 6216 | |||
| 6217 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | ibuf_max_size_update(srv_change_buffer_max_size); |
| 6218 | |||
| 6219 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | innobase_open_tables = ut::new_<hash_table_t>(200); |
| 6220 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | mysql_mutex_init(innobase_share_mutex_key.m_value, &innobase_share_mutex, |
| 6221 | MY_MUTEX_INIT_FAST); | ||
| 6222 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | mysql_mutex_init(commit_cond_mutex_key.m_value, &commit_cond_m, |
| 6223 | MY_MUTEX_INIT_FAST); | ||
| 6224 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | mysql_cond_init(commit_cond_key.m_value, &commit_cond); |
| 6225 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | mysql_mutex_init(resume_encryption_cond_mutex_key.m_value, |
| 6226 | &resume_encryption_cond_m, MY_MUTEX_INIT_FAST); | ||
| 6227 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | mysql_cond_init(resume_encryption_cond_key.m_value, &resume_encryption_cond); |
| 6228 | 11920 | innodb_inited = true; | |
| 6229 | #ifdef MYSQL_DYNAMIC_PLUGIN | ||
| 6230 | if (innobase_hton != p) { | ||
| 6231 | innobase_hton = reinterpret_cast<handlerton *>(p); | ||
| 6232 | *innobase_hton = *innodb_hton_ptr; | ||
| 6233 | } | ||
| 6234 | #endif /* MYSQL_DYNAMIC_PLUGIN */ | ||
| 6235 | |||
| 6236 | /* Do this as late as possible so server is fully starts up, | ||
| 6237 | since we might get some initial stats if user choose to turn | ||
| 6238 | on some counters from start up */ | ||
| 6239 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11918 times.
|
11920 | if (innobase_enable_monitor_counter) { |
| 6240 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innodb_enable_monitor_at_startup(innobase_enable_monitor_counter); |
| 6241 | } | ||
| 6242 | |||
| 6243 | /* Turn on monitor counters that are default on */ | ||
| 6244 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | srv_mon_default_on(); |
| 6245 | |||
| 6246 | /* Unit Tests */ | ||
| 6247 | #ifdef UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR | ||
| 6248 | unit_test_os_file_get_parent_dir(); | ||
| 6249 | #endif /* UNIV_ENABLE_UNIT_TEST_GET_PARENT_DIR */ | ||
| 6250 | |||
| 6251 | #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH | ||
| 6252 | test_make_filepath(); | ||
| 6253 | #endif /*UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH */ | ||
| 6254 | |||
| 6255 | #ifdef UNIV_ENABLE_DICT_STATS_TEST | ||
| 6256 | test_dict_stats_all(); | ||
| 6257 | #endif /*UNIV_ENABLE_DICT_STATS_TEST */ | ||
| 6258 | |||
| 6259 | #ifdef UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT | ||
| 6260 | #ifdef HAVE_UT_CHRONO_T | ||
| 6261 | test_row_raw_format_int(); | ||
| 6262 | #endif /* HAVE_UT_CHRONO_T */ | ||
| 6263 | #endif /* UNIV_ENABLE_UNIT_TEST_ROW_RAW_FORMAT_INT */ | ||
| 6264 | |||
| 6265 | 11920 | return 0; | |
| 6266 | 12007 | } | |
| 6267 | |||
| 6268 | /** Flush InnoDB redo logs to the file system. | ||
| 6269 | @param[in] hton InnoDB handlerton | ||
| 6270 | @param[in] binlog_group_flush true if we got invoked by binlog | ||
| 6271 | group commit during flush stage, false in other cases. | ||
| 6272 | @return false */ | ||
| 6273 | 5900423 | static bool innobase_flush_logs(handlerton *hton, bool binlog_group_flush) { | |
| 6274 |
1/2✓ Branch 0 taken 5900429 times.
✗ Branch 1 not taken.
|
5900423 | DBUG_TRACE; |
| 6275 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5900429 times.
|
5900429 | assert(hton == innodb_hton_ptr); |
| 6276 | |||
| 6277 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 5900396 times.
|
5900429 | if (srv_read_only_mode) { |
| 6278 | 33 | return false; | |
| 6279 | } | ||
| 6280 | |||
| 6281 | /* If !binlog_group_flush, we got invoked by FLUSH LOGS or similar. | ||
| 6282 | Else, we got invoked by binlog group commit during flush stage. */ | ||
| 6283 | |||
| 6284 |
4/4✓ Branch 0 taken 5826055 times.
✓ Branch 1 taken 74341 times.
✓ Branch 2 taken 87914 times.
✓ Branch 3 taken 5738141 times.
|
5900396 | if (binlog_group_flush && srv_flush_log_at_trx_commit == 0) { |
| 6285 | /* innodb_flush_log_at_trx_commit=0 | ||
| 6286 | (write and sync once per second). | ||
| 6287 | Do not flush the redo log during binlog group commit. */ | ||
| 6288 | |||
| 6289 | /* This could be unsafe if we grouped at least one DDL transaction, | ||
| 6290 | and we removed !trx->ddl_must_flush from condition which is checked | ||
| 6291 | inside trx_commit_complete_for_mysql() when we decide if we could | ||
| 6292 | skip the flush. */ | ||
| 6293 | 87914 | return false; | |
| 6294 | } | ||
| 6295 | |||
| 6296 | /* Signal and wait for all GTIDs to persist on disk. */ | ||
| 6297 |
2/2✓ Branch 0 taken 74341 times.
✓ Branch 1 taken 5738141 times.
|
5812482 | if (!binlog_group_flush) { |
| 6298 | 74341 | auto >id_persistor = clone_sys->get_gtid_persistor(); | |
| 6299 |
1/2✓ Branch 0 taken 74341 times.
✗ Branch 1 not taken.
|
74341 | gtid_persistor.wait_flush(true, true, nullptr); |
| 6300 | } | ||
| 6301 | |||
| 6302 | /* Flush the redo log buffer to the redo log file. | ||
| 6303 | Sync it to disc if we are in FLUSH LOGS, or if | ||
| 6304 | innodb_flush_log_at_trx_commit=1 | ||
| 6305 | (write and sync at each commit). */ | ||
| 6306 |
3/4✓ Branch 0 taken 5738141 times.
✓ Branch 1 taken 74341 times.
✓ Branch 2 taken 5812473 times.
✗ Branch 3 not taken.
|
11550623 | log_buffer_flush_to_disk(!binlog_group_flush || |
| 6307 |
1/2✓ Branch 0 taken 5738141 times.
✗ Branch 1 not taken.
|
5738141 | srv_flush_log_at_trx_commit == 1); |
| 6308 | |||
| 6309 | 5812473 | return false; | |
| 6310 | 5900420 | } | |
| 6311 | |||
| 6312 | /** Commits a transaction in an InnoDB database. */ | ||
| 6313 | 21554964 | void innobase_commit_low(trx_t *trx) /*!< in: transaction handle */ | |
| 6314 | { | ||
| 6315 |
2/2✓ Branch 0 taken 16757272 times.
✓ Branch 1 taken 4797722 times.
|
21554964 | if (trx_is_started(trx)) { |
| 6316 | 16757272 | const dberr_t error [[maybe_unused]] = trx_commit_for_mysql(trx); | |
| 6317 | // This is ut_ad not ut_a, because previously we did not have an assert | ||
| 6318 | // and nobody has noticed for a long time, so probably there is no much | ||
| 6319 | // harm in silencing this error. OTOH we believe it should no longer happen | ||
| 6320 | // after adding `true` as a second argument to TrxInInnoDB constructor call, | ||
| 6321 | // so we'd like to learn if the error can still happen. | ||
| 6322 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16757265 times.
|
16757256 | ut_ad(DB_SUCCESS == error); |
| 6323 | } | ||
| 6324 | 21554987 | trx->will_lock = 0; | |
| 6325 | 21554987 | } | |
| 6326 | |||
| 6327 | /** Stores the current binlog coordinates in the trx system header | ||
| 6328 | @param[in] hton InnoDB handlerton | ||
| 6329 | @param[in] thd MySQL thread handle */ | ||
| 6330 | 80 | static int innobase_store_binlog_info(handlerton *hton, THD *thd) noexcept { | |
| 6331 | 80 | DBUG_ENTER("innobase_store_binlog_info"); | |
| 6332 | |||
| 6333 | const char *file_name; | ||
| 6334 | unsigned long long pos; | ||
| 6335 | 80 | thd_binlog_pos(thd, &file_name, &pos); | |
| 6336 | |||
| 6337 | 80 | trx_sys_write_binlog_position("", std::numeric_limits<uint64_t>::max(), | |
| 6338 | file_name, pos); | ||
| 6339 | |||
| 6340 | 80 | innobase_flush_logs(hton, false); | |
| 6341 | |||
| 6342 | 80 | DBUG_RETURN(0); | |
| 6343 | } | ||
| 6344 | |||
| 6345 | /** Creates an InnoDB transaction struct for the thd if it does not yet have | ||
| 6346 | one. Starts a new InnoDB transaction if a transaction is not yet started. And | ||
| 6347 | assigns a new snapshot for a consistent read if the transaction does not yet | ||
| 6348 | have one. | ||
| 6349 | @return 0 */ | ||
| 6350 | 121 | static int innobase_start_trx_and_assign_read_view( | |
| 6351 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 6352 | THD *thd) /*!< in: MySQL thread handle of the user for | ||
| 6353 | whom the transaction should be committed */ | ||
| 6354 | { | ||
| 6355 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | DBUG_TRACE; |
| 6356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
|
121 | assert(hton == innodb_hton_ptr); |
| 6357 | |||
| 6358 | /* Create a new trx struct for thd, if it does not yet have one */ | ||
| 6359 | |||
| 6360 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | trx_t *trx = check_trx_exists(thd); |
| 6361 | |||
| 6362 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | TrxInInnoDB trx_in_innodb(trx); |
| 6363 | |||
| 6364 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | innobase_srv_conc_force_exit_innodb(trx); |
| 6365 | |||
| 6366 | /* The transaction should not be active yet, start it */ | ||
| 6367 |
2/4✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 121 times.
|
121 | ut_ad(!trx_is_started(trx)); |
| 6368 | |||
| 6369 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE); |
| 6370 | |||
| 6371 | /* Assign a read view if the transaction does not have it yet. | ||
| 6372 | Do this only if transaction is using REPEATABLE READ isolation | ||
| 6373 | level. */ | ||
| 6374 | 121 | trx->isolation_level = | |
| 6375 |
2/4✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
|
121 | innobase_trx_map_isolation_level(thd_get_trx_isolation(thd)); |
| 6376 | |||
| 6377 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) { |
| 6378 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | trx_assign_read_view(trx); |
| 6379 | } else { | ||
| 6380 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, | |
| 6381 | "InnoDB: WITH CONSISTENT SNAPSHOT" | ||
| 6382 | " was ignored because this phrase" | ||
| 6383 | " can only be used with" | ||
| 6384 | " REPEATABLE READ isolation level."); | ||
| 6385 | } | ||
| 6386 | |||
| 6387 | /* Set the MySQL flag to mark that there is an active transaction */ | ||
| 6388 | |||
| 6389 |
2/4✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
|
121 | innobase_register_trx(hton, current_thd, trx); |
| 6390 | |||
| 6391 | 121 | return 0; | |
| 6392 | 121 | } | |
| 6393 | |||
| 6394 | /** Creates an InnoDB transaction struct for the thd if it does not | ||
| 6395 | yet have one. Starts a new InnoDB transaction if a transaction is not | ||
| 6396 | yet started. And clones snapshot for a consistent read from another | ||
| 6397 | session, if it has one. | ||
| 6398 | @param[in] hton InnoDB handlerton | ||
| 6399 | @param[in] thd MySQL thread handle of the user for whom the | ||
| 6400 | transaction should be committed | ||
| 6401 | @param[in] from_thd MySQL thread handle of the user session from | ||
| 6402 | which the consistent read should be cloned | ||
| 6403 | @return 0 */ | ||
| 6404 | 21 | static int innobase_start_trx_and_clone_read_view(handlerton *hton, THD *thd, | |
| 6405 | THD *from_thd) { | ||
| 6406 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | DBUG_ENTER("innobase_start_trx_and_clone_read_view"); |
| 6407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | assert(hton == innodb_hton_ptr); |
| 6408 | |||
| 6409 | /* Get transaction handle from the donor session */ | ||
| 6410 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | trx_t *const from_trx = thd_to_trx(from_thd); |
| 6411 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | if (!from_trx) { |
| 6412 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, | |
| 6413 | "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was " | ||
| 6414 | "ignored because the specified session does not have " | ||
| 6415 | "an open transaction inside InnoDB."); | ||
| 6416 | |||
| 6417 | ✗ | DBUG_RETURN(0); | |
| 6418 | } | ||
| 6419 | |||
| 6420 | /* Create a new trx struct for thd, if it does not yet have one */ | ||
| 6421 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | trx_t *const trx = check_trx_exists(thd); |
| 6422 | |||
| 6423 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | innobase_srv_conc_force_exit_innodb(trx); |
| 6424 | |||
| 6425 | /* If the transaction is not started yet, start it */ | ||
| 6426 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE); |
| 6427 | |||
| 6428 | /* Clone the read view from the donor transaction. Do this only if | ||
| 6429 | transaction is using REPEATABLE READ isolation level. */ | ||
| 6430 | 21 | trx->isolation_level = | |
| 6431 |
2/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | innobase_trx_map_isolation_level(thd_get_trx_isolation(thd)); |
| 6432 | |||
| 6433 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
|
21 | if (trx->isolation_level != TRX_ISO_REPEATABLE_READ) { |
| 6434 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 6435 | "InnoDB: WITH CONSISTENT SNAPSHOT was ignored because " | ||
| 6436 | "this phrase can only be used with REPEATABLE READ " | ||
| 6437 | "isolation level."); | ||
| 6438 | } else { | ||
| 6439 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | locksys::Global_exclusive_latch_guard guard{UT_LOCATION_HERE}; |
| 6440 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | trx_sys_mutex_enter(); |
| 6441 |
4/8✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
|
20 | trx_mutex_enter(from_trx); |
| 6442 |
3/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 17 times.
|
20 | if (!trx_clone_read_view(trx, from_trx)) { |
| 6443 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | push_warning_printf(thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 6444 | "InnoDB: WITH CONSISTENT SNAPSHOT FROM SESSION was " | ||
| 6445 | "ignored because the target transaction has not " | ||
| 6446 | "been assigned a read view."); | ||
| 6447 | } | ||
| 6448 | 20 | } | |
| 6449 | |||
| 6450 | /* Set the MySQL flag to mark that there is an active transaction */ | ||
| 6451 |
2/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
|
21 | innobase_register_trx(hton, current_thd, trx); |
| 6452 | |||
| 6453 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | DBUG_RETURN(0); |
| 6454 | } | ||
| 6455 | |||
| 6456 | /** Commits a transaction in an InnoDB database or marks an SQL statement | ||
| 6457 | ended. | ||
| 6458 | @return 0 or deadlock error if the transaction was aborted by another | ||
| 6459 | higher priority transaction. */ | ||
| 6460 | 31716502 | static int innobase_commit(handlerton *hton, /*!< in: InnoDB handlerton */ | |
| 6461 | THD *thd, /*!< in: MySQL thread handle of the | ||
| 6462 | user for whom the transaction should | ||
| 6463 | be committed */ | ||
| 6464 | bool commit_trx) /*!< in: true - commit transaction | ||
| 6465 | false - the current SQL statement | ||
| 6466 | ended */ | ||
| 6467 | { | ||
| 6468 |
1/2✓ Branch 0 taken 31716551 times.
✗ Branch 1 not taken.
|
31716502 | DBUG_TRACE; |
| 6469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31716551 times.
|
31716551 | assert(hton == innodb_hton_ptr); |
| 6470 |
5/8✓ Branch 0 taken 31716551 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31716550 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1353 times.
✓ Branch 5 taken 31715197 times.
✓ Branch 6 taken 1353 times.
✗ Branch 7 not taken.
|
31716551 | DBUG_PRINT("trans", ("ending transaction")); |
| 6471 |
3/4✓ Branch 0 taken 27977985 times.
✓ Branch 1 taken 3738565 times.
✓ Branch 2 taken 27978011 times.
✗ Branch 3 not taken.
|
31716550 | DEBUG_SYNC_C("transaction_commit_start"); |
| 6472 | |||
| 6473 |
1/2✓ Branch 0 taken 31716551 times.
✗ Branch 1 not taken.
|
31716576 | trx_t *trx = check_trx_exists(thd); |
| 6474 | |||
| 6475 | /* We are about to check if the transaction is_aborted, and if it is, | ||
| 6476 | then we want to rollback, and otherwise we want to proceed. | ||
| 6477 | However it might happen that a different transaction, which has high priority | ||
| 6478 | will abort our transaction just after we do the test. | ||
| 6479 | To prevent that, we want to set TRX_FORCE_ROLLBACK_DISABLE flag on our trx, | ||
| 6480 | which is checked in RecLock::make_trx_hit_list and prevents high priority | ||
| 6481 | transaction from killing us. | ||
| 6482 | One way to do that is to call TrxInInnoDB with `true` as second argument. | ||
| 6483 | Note that innobase_commit is called not only on "real" COMMIT, but also | ||
| 6484 | after each statement (with commit_trx=false), so we need some logic to decide | ||
| 6485 | if we really plan to perform commit during this call. | ||
| 6486 | */ | ||
| 6487 | bool will_commit = | ||
| 6488 |
2/2✓ Branch 0 taken 29985341 times.
✓ Branch 1 taken 1731210 times.
|
61701905 | commit_trx || |
| 6489 |
3/4✓ Branch 0 taken 29985354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19810933 times.
✓ Branch 3 taken 10174421 times.
|
29985341 | (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); |
| 6490 |
1/2✓ Branch 0 taken 31716550 times.
✗ Branch 1 not taken.
|
31716564 | TrxInInnoDB trx_in_innodb(trx, will_commit); |
| 6491 | |||
| 6492 |
3/4✓ Branch 0 taken 31716553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 31716549 times.
|
31716550 | if (trx_in_innodb.is_aborted()) { |
| 6493 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | innobase_rollback(hton, thd, commit_trx); |
| 6494 | |||
| 6495 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd); |
| 6496 | } | ||
| 6497 | |||
| 6498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31716541 times.
|
31716549 | ut_ad(trx->dict_operation_lock_mode == 0); |
| 6499 | |||
| 6500 | /* Transaction is deregistered only in a commit or a rollback. If | ||
| 6501 | it is deregistered we know there cannot be resources to be freed | ||
| 6502 | and we could return immediately. For the time being, we play safe | ||
| 6503 | and do the cleanup though there should be nothing to clean up. */ | ||
| 6504 | |||
| 6505 |
5/8✓ Branch 0 taken 622866 times.
✓ Branch 1 taken 31093658 times.
✓ Branch 2 taken 622870 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 622870 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 31716528 times.
|
31716541 | if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { |
| 6506 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE); | |
| 6507 | } | ||
| 6508 | |||
| 6509 |
4/4✓ Branch 0 taken 19032531 times.
✓ Branch 1 taken 12683998 times.
✓ Branch 2 taken 5477606 times.
✓ Branch 3 taken 13554925 times.
|
31716529 | bool read_only = trx->read_only || trx->id == 0; |
| 6510 | |||
| 6511 |
2/2✓ Branch 0 taken 21542116 times.
✓ Branch 1 taken 10174413 times.
|
31716529 | if (will_commit) { |
| 6512 |
4/6✓ Branch 0 taken 21542122 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 21542119 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
21542116 | DBUG_EXECUTE_IF("crash_innodb_before_commit", DBUG_SUICIDE();); |
| 6513 | /* We were instructed to commit the whole transaction, or | ||
| 6514 | this is an SQL statement end and autocommit is on */ | ||
| 6515 | |||
| 6516 | /* We need current binlog position for mysqlbackup to work. */ | ||
| 6517 | |||
| 6518 |
2/2✓ Branch 0 taken 3447469 times.
✓ Branch 1 taken 18094650 times.
|
21542119 | if (!read_only) { |
| 6519 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3447456 times.
|
3447469 | while (innobase_commit_concurrency > 0) { |
| 6520 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | mysql_mutex_lock(&commit_cond_m); |
| 6521 | |||
| 6522 | 13 | ++commit_threads; | |
| 6523 | |||
| 6524 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (commit_threads <= innobase_commit_concurrency) { |
| 6525 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | mysql_mutex_unlock(&commit_cond_m); |
| 6526 | 13 | break; | |
| 6527 | } | ||
| 6528 | |||
| 6529 | ✗ | --commit_threads; | |
| 6530 | |||
| 6531 | ✗ | mysql_cond_wait(&commit_cond, &commit_cond_m); | |
| 6532 | |||
| 6533 | ✗ | mysql_mutex_unlock(&commit_cond_m); | |
| 6534 | } | ||
| 6535 | |||
| 6536 | /* The following call reads the binary log position of | ||
| 6537 | the transaction being committed. | ||
| 6538 | |||
| 6539 | Binary logging of other engines is not relevant to | ||
| 6540 | InnoDB as all InnoDB requires is that committing | ||
| 6541 | InnoDB transactions appear in the same order in the | ||
| 6542 | MySQL binary log as they appear in InnoDB logs, which | ||
| 6543 | is guaranteed by the server. | ||
| 6544 | |||
| 6545 | If the binary log is not enabled, or the transaction | ||
| 6546 | is not written to the binary log, the file name will | ||
| 6547 | be a NULL pointer. */ | ||
| 6548 | ulonglong pos; | ||
| 6549 | |||
| 6550 |
1/2✓ Branch 0 taken 3447469 times.
✗ Branch 1 not taken.
|
3447469 | thd_binlog_pos(thd, &trx->mysql_log_file_name, &pos); |
| 6551 | |||
| 6552 | 3447469 | trx->mysql_log_offset = static_cast<uint64_t>(pos); | |
| 6553 | |||
| 6554 | /* Don't do write + flush right now. For group commit | ||
| 6555 | to work we want to do the flush later. */ | ||
| 6556 | 3447469 | trx->flush_log_later = true; | |
| 6557 | } | ||
| 6558 | |||
| 6559 | /* If SE needs to persist GTID we must have a transaction. */ | ||
| 6560 |
3/4✓ Branch 0 taken 21542117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211 times.
✓ Branch 3 taken 21541906 times.
|
21542119 | if (thd->se_persists_gtid_explicit()) { |
| 6561 |
1/2✓ Branch 0 taken 211 times.
✗ Branch 1 not taken.
|
211 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 6562 | } | ||
| 6563 | |||
| 6564 |
1/2✓ Branch 0 taken 21542103 times.
✗ Branch 1 not taken.
|
21542117 | innobase_commit_low(trx); |
| 6565 | |||
| 6566 |
2/2✓ Branch 0 taken 3447465 times.
✓ Branch 1 taken 18094638 times.
|
21542103 | if (!read_only) { |
| 6567 | 3447465 | trx->flush_log_later = false; | |
| 6568 | |||
| 6569 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3447452 times.
|
3447465 | if (innobase_commit_concurrency > 0) { |
| 6570 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | mysql_mutex_lock(&commit_cond_m); |
| 6571 | |||
| 6572 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | ut_ad(commit_threads > 0); |
| 6573 | 13 | --commit_threads; | |
| 6574 | |||
| 6575 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | mysql_cond_signal(&commit_cond); |
| 6576 | |||
| 6577 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | mysql_mutex_unlock(&commit_cond_m); |
| 6578 | } | ||
| 6579 | } | ||
| 6580 | |||
| 6581 | 21542103 | trx_deregister_from_2pc(trx); | |
| 6582 | |||
| 6583 | /* Now do a write + flush of logs. */ | ||
| 6584 |
2/2✓ Branch 0 taken 3447464 times.
✓ Branch 1 taken 18094624 times.
|
21542088 | if (!read_only) { |
| 6585 |
1/2✓ Branch 0 taken 3447426 times.
✗ Branch 1 not taken.
|
3447464 | trx_commit_complete_for_mysql(trx); |
| 6586 | } | ||
| 6587 | |||
| 6588 | } else { | ||
| 6589 | /* We just mark the SQL statement ended and do not do a | ||
| 6590 | transaction commit */ | ||
| 6591 | |||
| 6592 | /* If we had reserved the auto-inc lock for some | ||
| 6593 | table in this SQL statement we release it now */ | ||
| 6594 | |||
| 6595 |
2/2✓ Branch 0 taken 10107452 times.
✓ Branch 1 taken 66961 times.
|
10174413 | if (!read_only) { |
| 6596 |
1/2✓ Branch 0 taken 10107462 times.
✗ Branch 1 not taken.
|
10107452 | lock_unlock_table_autoinc(trx); |
| 6597 | } | ||
| 6598 | |||
| 6599 | /* Store the current undo_no of the transaction so that we | ||
| 6600 | know where to roll back if we have to roll back the next | ||
| 6601 | SQL statement */ | ||
| 6602 | |||
| 6603 |
1/2✓ Branch 0 taken 10174421 times.
✗ Branch 1 not taken.
|
10174423 | trx_mark_sql_stat_end(trx); |
| 6604 | } | ||
| 6605 | |||
| 6606 | /* Reset the number AUTO-INC rows required */ | ||
| 6607 | 31716471 | trx->n_autoinc_rows = 0; | |
| 6608 | |||
| 6609 | /* This is a statement level variable. */ | ||
| 6610 | 31716471 | trx->fts_next_doc_id = 0; | |
| 6611 | |||
| 6612 |
1/2✓ Branch 0 taken 31716516 times.
✗ Branch 1 not taken.
|
31716471 | innobase_srv_conc_force_exit_innodb(trx); |
| 6613 | |||
| 6614 | 31716516 | return 0; | |
| 6615 | 31716520 | } | |
| 6616 | |||
| 6617 | /** Rolls back a transaction or the latest SQL statement. | ||
| 6618 | @return 0 or error number */ | ||
| 6619 | 721568 | static int innobase_rollback(handlerton *hton, /*!< in: InnoDB handlerton */ | |
| 6620 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 6621 | of the user whose transaction should | ||
| 6622 | be rolled back */ | ||
| 6623 | bool rollback_trx) /*!< in: true - rollback entire | ||
| 6624 | transaction false - rollback the | ||
| 6625 | current statement only */ | ||
| 6626 | { | ||
| 6627 |
1/2✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
|
721568 | DBUG_TRACE; |
| 6628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 721569 times.
|
721569 | assert(hton == innodb_hton_ptr); |
| 6629 |
5/8✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 721569 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 721568 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
721569 | DBUG_PRINT("trans", ("aborting transaction")); |
| 6630 | |||
| 6631 |
1/2✓ Branch 0 taken 721568 times.
✗ Branch 1 not taken.
|
721569 | trx_t *trx = check_trx_exists(thd); |
| 6632 | |||
| 6633 |
1/2✓ Branch 0 taken 721568 times.
✗ Branch 1 not taken.
|
721568 | TrxInInnoDB trx_in_innodb(trx); |
| 6634 | |||
| 6635 |
6/10✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 721249 times.
✓ Branch 3 taken 320 times.
✓ Branch 4 taken 721249 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 721249 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 721569 times.
|
721568 | ut_ad(trx_in_innodb.is_aborted() || |
| 6636 | (trx->dict_operation_lock_mode == 0 && | ||
| 6637 | trx->dict_operation == TRX_DICT_OP_NONE)); | ||
| 6638 | |||
| 6639 |
1/2✓ Branch 0 taken 721568 times.
✗ Branch 1 not taken.
|
721569 | innobase_srv_conc_force_exit_innodb(trx); |
| 6640 | |||
| 6641 | /* Reset the number AUTO-INC rows required */ | ||
| 6642 | |||
| 6643 | 721568 | trx->n_autoinc_rows = 0; | |
| 6644 | |||
| 6645 | /* If we had reserved the auto-inc lock for some table (if | ||
| 6646 | we come here to roll back the latest SQL statement) we | ||
| 6647 | release it now before a possibly lengthy rollback */ | ||
| 6648 | |||
| 6649 |
3/4✓ Branch 0 taken 721569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 721249 times.
✓ Branch 3 taken 320 times.
|
721568 | if (!trx_in_innodb.is_aborted()) { |
| 6650 |
1/2✓ Branch 0 taken 721249 times.
✗ Branch 1 not taken.
|
721249 | lock_unlock_table_autoinc(trx); |
| 6651 | } | ||
| 6652 | |||
| 6653 | /* This is a statement level variable. */ | ||
| 6654 | |||
| 6655 | 721569 | trx->fts_next_doc_id = 0; | |
| 6656 | |||
| 6657 | dberr_t error; | ||
| 6658 | |||
| 6659 |
4/4✓ Branch 0 taken 712830 times.
✓ Branch 1 taken 8739 times.
✓ Branch 2 taken 714915 times.
✓ Branch 3 taken 6654 times.
|
1434399 | if (rollback_trx || |
| 6660 |
3/4✓ Branch 0 taken 712830 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 706176 times.
✓ Branch 3 taken 6654 times.
|
712830 | !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 6661 |
1/2✓ Branch 0 taken 714903 times.
✗ Branch 1 not taken.
|
714915 | error = trx_rollback_for_mysql(trx); |
| 6662 | |||
| 6663 |
2/4✓ Branch 0 taken 714903 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 714903 times.
|
714903 | ut_ad(trx_can_be_handled_by_current_thread_or_is_hp_victim(trx)); |
| 6664 |
2/2✓ Branch 0 taken 308 times.
✓ Branch 1 taken 714595 times.
|
714903 | if (trx->state.load(std::memory_order_relaxed) == |
| 6665 | TRX_STATE_FORCED_ROLLBACK) { | ||
| 6666 | #ifdef UNIV_DEBUG | ||
| 6667 | char buffer[1024]; | ||
| 6668 | |||
| 6669 |
1/2✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
|
308 | ib::info(ER_IB_MSG_548) |
| 6670 |
1/2✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
|
308 | << "Forced rollback : " |
| 6671 |
2/4✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
|
308 | << thd_security_context(thd, buffer, sizeof(buffer), 512); |
| 6672 | #endif /* UNIV_DEBUG */ | ||
| 6673 | 308 | trx->state.store(TRX_STATE_NOT_STARTED, std::memory_order_relaxed); | |
| 6674 | } | ||
| 6675 | |||
| 6676 | 714903 | trx_deregister_from_2pc(trx); | |
| 6677 | |||
| 6678 | } else { | ||
| 6679 |
1/2✓ Branch 0 taken 6654 times.
✗ Branch 1 not taken.
|
6654 | error = trx_rollback_last_sql_stat_for_mysql(trx); |
| 6680 | } | ||
| 6681 | |||
| 6682 |
1/2✓ Branch 0 taken 721557 times.
✗ Branch 1 not taken.
|
1443114 | return convert_error_code_to_mysql(error, 0, trx->mysql_thd); |
| 6683 | 721557 | } | |
| 6684 | |||
| 6685 | /** Rolls back a transaction | ||
| 6686 | @return 0 or error number */ | ||
| 6687 | 16672429 | static int innobase_rollback_trx(trx_t *trx) /*!< in: transaction */ | |
| 6688 | { | ||
| 6689 | 16672429 | dberr_t error = DB_SUCCESS; | |
| 6690 | |||
| 6691 |
1/2✓ Branch 0 taken 16672681 times.
✗ Branch 1 not taken.
|
16672429 | DBUG_TRACE; |
| 6692 |
5/8✓ Branch 0 taken 16672572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16672656 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1127 times.
✓ Branch 5 taken 16671529 times.
✓ Branch 6 taken 1127 times.
✗ Branch 7 not taken.
|
16672681 | DBUG_PRINT("trans", ("aborting transaction")); |
| 6693 | |||
| 6694 |
1/2✓ Branch 0 taken 16672650 times.
✗ Branch 1 not taken.
|
16672656 | innobase_srv_conc_force_exit_innodb(trx); |
| 6695 | |||
| 6696 | /* If we had reserved the auto-inc lock for some table (if | ||
| 6697 | we come here to roll back the latest SQL statement) we | ||
| 6698 | release it now before a possibly lengthy rollback */ | ||
| 6699 |
3/4✓ Branch 0 taken 16672625 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16672618 times.
✓ Branch 3 taken 7 times.
|
16672650 | if (!TrxInInnoDB::is_aborted(trx)) { |
| 6700 |
1/2✓ Branch 0 taken 16672635 times.
✗ Branch 1 not taken.
|
16672618 | lock_unlock_table_autoinc(trx); |
| 6701 | } | ||
| 6702 | |||
| 6703 |
2/2✓ Branch 0 taken 386 times.
✓ Branch 1 taken 16672329 times.
|
16672642 | if (trx_is_rseg_updated(trx)) { |
| 6704 |
1/2✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
|
386 | error = trx_rollback_for_mysql(trx); |
| 6705 | } else { | ||
| 6706 | 16672329 | trx->will_lock = 0; | |
| 6707 | } | ||
| 6708 | |||
| 6709 |
1/2✓ Branch 0 taken 16672556 times.
✗ Branch 1 not taken.
|
33345362 | return convert_error_code_to_mysql(error, 0, trx->mysql_thd); |
| 6710 | 16672556 | } | |
| 6711 | |||
| 6712 | /** Rolls back a transaction to a savepoint. | ||
| 6713 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 6714 | given name */ | ||
| 6715 | 7795 | static int innobase_rollback_to_savepoint( | |
| 6716 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 6717 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 6718 | of the user whose transaction should | ||
| 6719 | be rolled back to savepoint */ | ||
| 6720 | void *savepoint) /*!< in: savepoint data */ | ||
| 6721 | { | ||
| 6722 |
1/2✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
|
7795 | DBUG_TRACE; |
| 6723 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7795 times.
|
7795 | assert(hton == innodb_hton_ptr); |
| 6724 | |||
| 6725 |
1/2✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
|
7795 | trx_t *trx = check_trx_exists(thd); |
| 6726 | |||
| 6727 |
1/2✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
|
7795 | TrxInInnoDB trx_in_innodb(trx); |
| 6728 | |||
| 6729 |
1/2✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
|
7795 | innobase_srv_conc_force_exit_innodb(trx); |
| 6730 | |||
| 6731 | /* TODO: use provided savepoint data area to store savepoint data */ | ||
| 6732 | |||
| 6733 | char name[64]; | ||
| 6734 | |||
| 6735 |
1/2✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
|
7795 | longlong2str((ulint)savepoint, name, 36); |
| 6736 | |||
| 6737 | int64_t mysql_binlog_cache_pos; | ||
| 6738 | |||
| 6739 | dberr_t error = | ||
| 6740 |
1/2✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
|
7795 | trx_rollback_to_savepoint_for_mysql(trx, name, &mysql_binlog_cache_pos); |
| 6741 | |||
| 6742 |
3/4✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 7778 times.
|
7795 | if (error == DB_SUCCESS && trx->fts_trx != nullptr) { |
| 6743 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | fts_savepoint_rollback(trx, name); |
| 6744 | } | ||
| 6745 | |||
| 6746 |
1/2✓ Branch 0 taken 7795 times.
✗ Branch 1 not taken.
|
15590 | return convert_error_code_to_mysql(error, 0, nullptr); |
| 6747 | 7795 | } | |
| 6748 | |||
| 6749 | /** Check whether innodb state allows to safely release MDL locks after | ||
| 6750 | rollback to savepoint. | ||
| 6751 | When binlog is on, MDL locks acquired after savepoint unit are not | ||
| 6752 | released if there are any locks held in InnoDB. | ||
| 6753 | @return true if it is safe, false if its not safe. */ | ||
| 6754 | 7780 | static bool innobase_rollback_to_savepoint_can_release_mdl( | |
| 6755 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 6756 | THD *thd) /*!< in: handle to the MySQL thread | ||
| 6757 | of the user whose transaction should | ||
| 6758 | be rolled back to savepoint */ | ||
| 6759 | { | ||
| 6760 |
1/2✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
|
7780 | DBUG_TRACE; |
| 6761 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7780 times.
|
7780 | assert(hton == innodb_hton_ptr); |
| 6762 | |||
| 6763 |
1/2✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
|
7780 | trx_t *trx = check_trx_exists(thd); |
| 6764 | |||
| 6765 |
1/2✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
|
7780 | TrxInInnoDB trx_in_innodb(trx); |
| 6766 | |||
| 6767 |
2/4✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7780 times.
|
7780 | ut_ad(thd == current_thd); |
| 6768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7780 times.
|
7780 | ut_ad(trx->lock.wait_lock == nullptr); |
| 6769 |
1/2✓ Branch 0 taken 7780 times.
✗ Branch 1 not taken.
|
15560 | return UT_LIST_GET_LEN(trx->lock.trx_locks) == 0; |
| 6770 | 7780 | } | |
| 6771 | |||
| 6772 | /** Release transaction savepoint name. | ||
| 6773 | @return 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the | ||
| 6774 | given name */ | ||
| 6775 | 117 | static int innobase_release_savepoint( | |
| 6776 | handlerton *hton, /*!< in: handlerton for InnoDB */ | ||
| 6777 | THD *thd, /*!< in: handle to the MySQL thread | ||
| 6778 | of the user whose transaction's | ||
| 6779 | savepoint should be released */ | ||
| 6780 | void *savepoint) /*!< in: savepoint data */ | ||
| 6781 | { | ||
| 6782 | dberr_t error; | ||
| 6783 | trx_t *trx; | ||
| 6784 | char name[64]; | ||
| 6785 | |||
| 6786 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | DBUG_TRACE; |
| 6787 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
|
117 | assert(hton == innodb_hton_ptr); |
| 6788 | |||
| 6789 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | trx = check_trx_exists(thd); |
| 6790 | |||
| 6791 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | TrxInInnoDB trx_in_innodb(trx); |
| 6792 | |||
| 6793 | /* TODO: use provided savepoint data area to store savepoint data */ | ||
| 6794 | |||
| 6795 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | longlong2str((ulint)savepoint, name, 36); |
| 6796 | |||
| 6797 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | error = trx_release_savepoint_for_mysql(trx, name); |
| 6798 | |||
| 6799 |
3/4✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 105 times.
|
117 | if (error == DB_SUCCESS && trx->fts_trx != nullptr) { |
| 6800 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | fts_savepoint_release(trx, name); |
| 6801 | } | ||
| 6802 | |||
| 6803 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
234 | return convert_error_code_to_mysql(error, 0, nullptr); |
| 6804 | 117 | } | |
| 6805 | |||
| 6806 | /** Sets a transaction savepoint. | ||
| 6807 | @return always 0, that is, always succeeds */ | ||
| 6808 | 15388 | static int innobase_savepoint( | |
| 6809 | handlerton *hton, /*!< in: handle to the InnoDB handlerton */ | ||
| 6810 | THD *thd, /*!< in: handle to the MySQL thread */ | ||
| 6811 | void *savepoint) /*!< in: savepoint data */ | ||
| 6812 | { | ||
| 6813 |
1/2✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
|
15388 | DBUG_TRACE; |
| 6814 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15388 times.
|
15388 | assert(hton == innodb_hton_ptr); |
| 6815 | |||
| 6816 | /* In the autocommit mode there is no sense to set a savepoint | ||
| 6817 | (unless we are in sub-statement), so SQL layer ensures that | ||
| 6818 | this method is never called in such situation. */ | ||
| 6819 | |||
| 6820 |
1/2✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
|
15388 | trx_t *trx = check_trx_exists(thd); |
| 6821 | |||
| 6822 |
1/2✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
|
15388 | TrxInInnoDB trx_in_innodb(trx); |
| 6823 | |||
| 6824 |
1/2✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
|
15388 | innobase_srv_conc_force_exit_innodb(trx); |
| 6825 | |||
| 6826 | /* Cannot happen outside of transaction */ | ||
| 6827 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15388 times.
|
15388 | assert(trx_is_registered_for_2pc(trx)); |
| 6828 | |||
| 6829 | /* TODO: use provided savepoint data area to store savepoint data */ | ||
| 6830 | char name[64]; | ||
| 6831 | |||
| 6832 |
1/2✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
|
15388 | longlong2str((ulint)savepoint, name, 36); |
| 6833 | |||
| 6834 |
1/2✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
|
15388 | dberr_t error = trx_savepoint_for_mysql(trx, name, 0); |
| 6835 | |||
| 6836 |
3/4✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 15336 times.
|
15388 | if (error == DB_SUCCESS && trx->fts_trx != nullptr) { |
| 6837 |
1/2✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
|
52 | fts_savepoint_take(trx->fts_trx, name); |
| 6838 | } | ||
| 6839 | |||
| 6840 |
1/2✓ Branch 0 taken 15388 times.
✗ Branch 1 not taken.
|
30776 | return convert_error_code_to_mysql(error, 0, nullptr); |
| 6841 | 15388 | } | |
| 6842 | |||
| 6843 | /** Frees a possible InnoDB trx object associated with the current THD. | ||
| 6844 | @return 0 or error number */ | ||
| 6845 | 16672527 | static int innobase_close_connection( | |
| 6846 | handlerton *hton, /*!< in: innobase handlerton */ | ||
| 6847 | THD *thd) /*!< in: handle to the MySQL thread of the user | ||
| 6848 | whose resources should be free'd */ | ||
| 6849 | { | ||
| 6850 |
1/2✓ Branch 0 taken 16672587 times.
✗ Branch 1 not taken.
|
16672527 | DBUG_TRACE; |
| 6851 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16672587 times.
|
16672587 | assert(hton == innodb_hton_ptr); |
| 6852 | |||
| 6853 |
1/2✓ Branch 0 taken 16672585 times.
✗ Branch 1 not taken.
|
16672587 | trx_t *trx = thd_to_trx(thd); |
| 6854 | 16672585 | bool free_trx = false; | |
| 6855 | |||
| 6856 | /* During server initialization MySQL layer will try to open | ||
| 6857 | some of the master-slave tables those residing in InnoDB. | ||
| 6858 | After MySQL layer is done with needed checks these tables | ||
| 6859 | are closed followed by invocation of close_connection on the | ||
| 6860 | associated thd. | ||
| 6861 | |||
| 6862 | close_connection rolls back the trx and then frees it. | ||
| 6863 | Once trx is freed thd should avoid maintaining reference to | ||
| 6864 | it else it can be classified as stale reference. | ||
| 6865 | |||
| 6866 | Re-invocation of innodb_close_connection on same thd should | ||
| 6867 | get trx as NULL. */ | ||
| 6868 | |||
| 6869 |
2/2✓ Branch 0 taken 16672416 times.
✓ Branch 1 taken 169 times.
|
16672585 | if (trx != nullptr) { |
| 6870 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16672396 times.
|
16672416 | ut_ad(trx->mysql_thd == thd); |
| 6871 |
1/2✓ Branch 0 taken 16672325 times.
✗ Branch 1 not taken.
|
16672396 | TrxInInnoDB trx_in_innodb(trx); |
| 6872 | |||
| 6873 |
2/4✓ Branch 0 taken 16672319 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16672319 times.
|
16672325 | if (trx_in_innodb.is_aborted()) { |
| 6874 | ✗ | while (trx_is_started(trx)) { | |
| 6875 | ✗ | std::this_thread::sleep_for(std::chrono::microseconds(20)); | |
| 6876 | } | ||
| 6877 | } | ||
| 6878 | |||
| 6879 |
5/8✓ Branch 0 taken 16672159 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 16672352 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16672352 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 16672359 times.
|
16672319 | if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { |
| 6880 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE); | |
| 6881 | } | ||
| 6882 | |||
| 6883 | /* Disconnect causes rollback in the following cases: | ||
| 6884 | - trx is not started, or | ||
| 6885 | - trx is in *not* in PREPARED state, or | ||
| 6886 | - trx has not updated any persistent data. | ||
| 6887 | TODO/FIXME: it does not make sense to initiate rollback | ||
| 6888 | in the 1st and 3rd case. */ | ||
| 6889 |
3/4✓ Branch 0 taken 16672342 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16672340 times.
|
16672359 | if (trx_is_started(trx)) { |
| 6890 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | if (trx_state_eq(trx, TRX_STATE_PREPARED)) { |
| 6891 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (trx_is_redo_rseg_updated(trx)) { |
| 6892 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_disconnect_prepared(trx); |
| 6893 | } else { | ||
| 6894 | ✗ | trx_rollback_for_mysql(trx); | |
| 6895 | ✗ | trx_deregister_from_2pc(trx); | |
| 6896 | ✗ | free_trx = true; | |
| 6897 | } | ||
| 6898 | } else { | ||
| 6899 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_CLOSING_CONNECTION_ROLLS_BACK, | |
| 6900 | trx->undo_no); | ||
| 6901 | ✗ | ut_d(ib::warn(ER_IB_MSG_549) | |
| 6902 | << "trx: " << trx << " started on: " | ||
| 6903 | << innobase_basename(trx->start_file) << ":" << trx->start_line); | ||
| 6904 | ✗ | innobase_rollback_trx(trx); | |
| 6905 | ✗ | free_trx = true; | |
| 6906 | } | ||
| 6907 | } else { | ||
| 6908 |
1/2✓ Branch 0 taken 16672325 times.
✗ Branch 1 not taken.
|
16672340 | innobase_rollback_trx(trx); |
| 6909 | 16672325 | free_trx = true; | |
| 6910 | } | ||
| 6911 | 16672327 | } | |
| 6912 | |||
| 6913 | /* Free trx only after TrxInInnoDB is deleted. */ | ||
| 6914 |
2/2✓ Branch 0 taken 16672374 times.
✓ Branch 1 taken 173 times.
|
16672547 | if (free_trx) { |
| 6915 |
1/2✓ Branch 0 taken 16672423 times.
✗ Branch 1 not taken.
|
16672374 | trx_free_for_mysql(trx); |
| 6916 | } | ||
| 6917 | |||
| 6918 |
1/2✓ Branch 0 taken 16672604 times.
✗ Branch 1 not taken.
|
16672596 | ut::delete_(thd_to_innodb_session(thd)); |
| 6919 | |||
| 6920 |
1/2✓ Branch 0 taken 16672602 times.
✗ Branch 1 not taken.
|
16672601 | thd_to_innodb_session(thd) = nullptr; |
| 6921 | |||
| 6922 | 16672601 | return 0; | |
| 6923 | 16672602 | } | |
| 6924 | |||
| 6925 | /** Cancel any pending lock request associated with the current THD. */ | ||
| 6926 | 1477 | static void innobase_kill_connection( | |
| 6927 | handlerton *hton, /*!< in: innobase handlerton */ | ||
| 6928 | THD *thd) /*!< in: handle to the MySQL thread being | ||
| 6929 | killed */ | ||
| 6930 | { | ||
| 6931 |
1/2✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
|
1477 | DBUG_TRACE; |
| 6932 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1477 times.
|
1477 | assert(hton == innodb_hton_ptr); |
| 6933 | |||
| 6934 |
1/2✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
|
1477 | trx_t *trx = thd_to_trx(thd); |
| 6935 | |||
| 6936 |
1/2✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
|
1477 | if (trx != nullptr) { |
| 6937 | /* Cancel a pending lock request if there are any */ | ||
| 6938 |
2/4✓ Branch 0 taken 1477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1477 times.
✗ Branch 3 not taken.
|
1477 | lock_cancel_if_waiting_and_release({trx}); |
| 6939 | } | ||
| 6940 | 1477 | } | |
| 6941 | |||
| 6942 | /** ** InnoDB database tables | ||
| 6943 | *****************************************************************************/ | ||
| 6944 | |||
| 6945 | /** The requested compressed page size (key_block_size) | ||
| 6946 | is given in kilobytes. If it is a valid number, store | ||
| 6947 | that value as the number of log2 shifts from 512 in | ||
| 6948 | zip_ssize. Zero means it is not compressed. */ | ||
| 6949 | 807 | static uint32_t get_zip_shift_size(ulint key_block_size) { | |
| 6950 | uint32_t zssize; /* Zip Shift Size */ | ||
| 6951 | uint32_t kbsize; /* Key Block Size */ | ||
| 6952 | const uint32_t zip_ssize_max = | ||
| 6953 | 1614 | std::min(static_cast<uint32_t>(UNIV_PAGE_SSIZE_MAX), | |
| 6954 | 807 | static_cast<uint32_t>(PAGE_ZIP_SSIZE_MAX)); | |
| 6955 |
2/2✓ Branch 0 taken 2085 times.
✓ Branch 1 taken 19 times.
|
2104 | for (zssize = kbsize = 1; zssize <= zip_ssize_max; zssize++, kbsize <<= 1) { |
| 6956 |
2/2✓ Branch 0 taken 788 times.
✓ Branch 1 taken 1297 times.
|
2085 | if (kbsize == key_block_size) { |
| 6957 | 788 | return (zssize); | |
| 6958 | } | ||
| 6959 | } | ||
| 6960 | 19 | return (0); | |
| 6961 | } | ||
| 6962 | |||
| 6963 | /** Get real row type for the table created based on one specified by user, | ||
| 6964 | CREATE TABLE options and SE capabilities. | ||
| 6965 | |||
| 6966 | @note The current code in this method is redundant with/copy of code from | ||
| 6967 | create_table_info_t::innobase_table_flags(). This is temporary workaround. | ||
| 6968 | In future this method will always return ROW_TYPE_DYNAMIC | ||
| 6969 | (which is suitable for intrisinc temporary tables) | ||
| 6970 | and rely on adjusting row format in table definition at ha_innobase::create() | ||
| 6971 | or ha_innobase::prepare_inplace_alter_table() time. | ||
| 6972 | */ | ||
| 6973 | 855112 | enum row_type ha_innobase::get_real_row_type( | |
| 6974 | const HA_CREATE_INFO *create_info) const { | ||
| 6975 | 855112 | const bool is_temp = create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 6976 | 855112 | row_type rt = create_info->row_type; | |
| 6977 | |||
| 6978 |
4/4✓ Branch 0 taken 275280 times.
✓ Branch 1 taken 579832 times.
✓ Branch 2 taken 229056 times.
✓ Branch 3 taken 46224 times.
|
855112 | if (is_temp && (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) { |
| 6979 | 229056 | return (ROW_TYPE_DYNAMIC); | |
| 6980 | } | ||
| 6981 | |||
| 6982 |
2/2✓ Branch 0 taken 255 times.
✓ Branch 1 taken 187333 times.
|
187588 | if (rt == ROW_TYPE_DEFAULT && create_info->key_block_size && |
| 6983 |
10/10✓ Branch 0 taken 187588 times.
✓ Branch 1 taken 438468 times.
✓ Branch 2 taken 242 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 235 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 224 times.
✓ Branch 8 taken 225 times.
✓ Branch 9 taken 625831 times.
|
813655 | get_zip_shift_size(create_info->key_block_size) && !is_temp && |
| 6984 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
|
11 | (srv_file_per_table || tablespace_is_shared_space(create_info))) { |
| 6985 | 225 | rt = ROW_TYPE_COMPRESSED; | |
| 6986 | } | ||
| 6987 | |||
| 6988 |
4/4✓ Branch 0 taken 437616 times.
✓ Branch 1 taken 1067 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 187361 times.
|
626056 | switch (rt) { |
| 6989 | 437616 | case ROW_TYPE_REDUNDANT: | |
| 6990 | case ROW_TYPE_DYNAMIC: | ||
| 6991 | case ROW_TYPE_COMPACT: | ||
| 6992 | 437616 | return (rt); | |
| 6993 | 1067 | case ROW_TYPE_COMPRESSED: | |
| 6994 |
6/6✓ Branch 0 taken 1023 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1010 times.
✓ Branch 4 taken 1013 times.
✓ Branch 5 taken 54 times.
|
1080 | if (!is_temp && |
| 6995 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
|
13 | (srv_file_per_table || tablespace_is_shared_space(create_info))) { |
| 6996 | 1013 | return (rt); | |
| 6997 | } else { | ||
| 6998 | 54 | return (ROW_TYPE_DYNAMIC); | |
| 6999 | } | ||
| 7000 | 12 | case ROW_TYPE_NOT_USED: | |
| 7001 | case ROW_TYPE_FIXED: | ||
| 7002 | case ROW_TYPE_PAGED: | ||
| 7003 | 12 | return (ROW_TYPE_DYNAMIC); | |
| 7004 | 187361 | case ROW_TYPE_DEFAULT: | |
| 7005 | default: | ||
| 7006 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 187261 times.
✗ Branch 3 not taken.
|
187361 | switch (innodb_default_row_format) { |
| 7007 | 17 | case DEFAULT_ROW_FORMAT_REDUNDANT: | |
| 7008 | 17 | return (ROW_TYPE_REDUNDANT); | |
| 7009 | 83 | case DEFAULT_ROW_FORMAT_COMPACT: | |
| 7010 | 83 | return (ROW_TYPE_COMPACT); | |
| 7011 | 187261 | case DEFAULT_ROW_FORMAT_DYNAMIC: | |
| 7012 | 187261 | return (ROW_TYPE_DYNAMIC); | |
| 7013 | ✗ | default: | |
| 7014 | ✗ | ut_d(ut_error); | |
| 7015 | ut_o(return (ROW_TYPE_DYNAMIC)); | ||
| 7016 | } | ||
| 7017 | } | ||
| 7018 | } | ||
| 7019 | |||
| 7020 | /** Get the table flags to use for the statement. | ||
| 7021 | @return table flags */ | ||
| 7022 | |||
| 7023 | 268403376 | handler::Table_flags ha_innobase::table_flags() const { | |
| 7024 | 268403376 | THD *thd = ha_thd(); | |
| 7025 | 268405077 | handler::Table_flags flags = m_int_table_flags; | |
| 7026 | |||
| 7027 | /* If querying the table flags when no table_share is given, | ||
| 7028 | then we must check if the table to be created/checked is partitioned. | ||
| 7029 | */ | ||
| 7030 |
6/6✓ Branch 0 taken 3044029 times.
✓ Branch 1 taken 265361048 times.
✓ Branch 2 taken 19372 times.
✓ Branch 3 taken 3024700 times.
✓ Branch 4 taken 19372 times.
✓ Branch 5 taken 268385748 times.
|
268405077 | if (table_share == nullptr && thd_get_work_part_info(thd) != nullptr) { |
| 7031 | /* Currently ha_innopart does not support | ||
| 7032 | all InnoDB features such as GEOMETRY, FULLTEXT etc. */ | ||
| 7033 | 19372 | flags &= ~(HA_INNOPART_DISABLED_TABLE_FLAGS); | |
| 7034 | } | ||
| 7035 | |||
| 7036 | /* Temporary table provides accurate record count */ | ||
| 7037 |
2/2✓ Branch 0 taken 265361060 times.
✓ Branch 1 taken 3044060 times.
|
268405120 | if (table_share != nullptr && |
| 7038 |
2/2✓ Branch 0 taken 857466 times.
✓ Branch 1 taken 264503594 times.
|
265361060 | table_share->table_category == TABLE_CATEGORY_TEMPORARY) { |
| 7039 | 857466 | flags |= HA_STATS_RECORDS_IS_EXACT; | |
| 7040 | } | ||
| 7041 | |||
| 7042 | /* Need to use tx_isolation here since table flags is (also) | ||
| 7043 | called before prebuilt is inited. */ | ||
| 7044 | |||
| 7045 | 268405120 | ulong const tx_isolation = thd_tx_isolation(thd); | |
| 7046 | |||
| 7047 |
2/2✓ Branch 0 taken 164710370 times.
✓ Branch 1 taken 103694614 times.
|
268404984 | if (tx_isolation <= ISO_READ_COMMITTED) { |
| 7048 | 164710370 | return (flags); | |
| 7049 | } | ||
| 7050 | |||
| 7051 | 103694614 | return (flags | HA_BINLOG_STMT_CAPABLE); | |
| 7052 | } | ||
| 7053 | |||
| 7054 | /** Returns the table type (storage engine name). | ||
| 7055 | @return table type */ | ||
| 7056 | |||
| 7057 | 147044 | const char *ha_innobase::table_type() const { return (innobase_hton_name); } | |
| 7058 | |||
| 7059 | /** Returns the operations supported for indexes. | ||
| 7060 | @return flags of supported operations */ | ||
| 7061 | |||
| 7062 | 45938833 | ulong ha_innobase::index_flags(uint key, uint, bool) const { | |
| 7063 |
2/2✓ Branch 0 taken 17639 times.
✓ Branch 1 taken 45921194 times.
|
45938833 | if (table_share->key_info[key].algorithm == HA_KEY_ALG_FULLTEXT) { |
| 7064 | 17639 | return (0); | |
| 7065 | } | ||
| 7066 | |||
| 7067 | 45921194 | ulong flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE | | |
| 7068 | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN; | ||
| 7069 | |||
| 7070 | /* For spatial index, we don't support descending scan | ||
| 7071 | and ICP so far. */ | ||
| 7072 |
2/2✓ Branch 0 taken 29388 times.
✓ Branch 1 taken 45891806 times.
|
45921194 | if (table_share->key_info[key].flags & HA_SPATIAL) { |
| 7073 | 29388 | flags = HA_READ_NEXT | HA_READ_ORDER | HA_READ_RANGE | HA_KEYREAD_ONLY | | |
| 7074 | HA_KEY_SCAN_NOT_ROR; | ||
| 7075 | 29388 | return (flags); | |
| 7076 | } | ||
| 7077 | |||
| 7078 | /* For dd tables mysql.*, we disable ICP for them, | ||
| 7079 | it's for avoiding recusively access same page. */ | ||
| 7080 | /* TODO: Remove these code once the recursiveely access issue which | ||
| 7081 | caused by ICP fixed. */ | ||
| 7082 | 45891806 | const char *dbname = table_share->db.str; | |
| 7083 |
4/4✓ Branch 0 taken 43735436 times.
✓ Branch 1 taken 2156370 times.
✓ Branch 2 taken 33138311 times.
✓ Branch 3 taken 10597125 times.
|
45891806 | if (dbname && strstr(dbname, dict_sys_t::s_dd_space_name) != nullptr && |
| 7084 |
2/2✓ Branch 0 taken 32908942 times.
✓ Branch 1 taken 229369 times.
|
33138311 | strlen(dbname) == 5) { |
| 7085 | 32908942 | flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE | | |
| 7086 | HA_KEYREAD_ONLY; | ||
| 7087 | } | ||
| 7088 | |||
| 7089 | /* Multi-valued keys don't support ordered retrieval, neither they're | ||
| 7090 | suitable for keyread only retrieval. */ | ||
| 7091 |
2/2✓ Branch 0 taken 6326 times.
✓ Branch 1 taken 45885480 times.
|
45891806 | if (table_share->key_info[key].flags & HA_MULTI_VALUED_KEY) { |
| 7092 | 6326 | flags &= ~(HA_READ_ORDER | HA_KEYREAD_ONLY); | |
| 7093 | } | ||
| 7094 | |||
| 7095 | 45891806 | return (flags); | |
| 7096 | } | ||
| 7097 | |||
| 7098 | /** Returns the maximum number of keys. | ||
| 7099 | @return MAX_KEY */ | ||
| 7100 | |||
| 7101 | 626828 | uint ha_innobase::max_supported_keys() const { return (MAX_KEY); } | |
| 7102 | |||
| 7103 | /** Returns the maximum key length. | ||
| 7104 | @return maximum supported key length, in bytes */ | ||
| 7105 | |||
| 7106 | 1424972 | uint ha_innobase::max_supported_key_length() const { | |
| 7107 | /* An InnoDB page must store >= 2 keys; a secondary key record | ||
| 7108 | must also contain the primary key value. Therefore, if both | ||
| 7109 | the primary key and the secondary key are at this maximum length, | ||
| 7110 | it must be less than 1/4th of the free space on a page including | ||
| 7111 | record overhead. | ||
| 7112 | |||
| 7113 | MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072. | ||
| 7114 | |||
| 7115 | For page sizes = 16k, InnoDB historically reported 3500 bytes here, | ||
| 7116 | But the MySQL limit of 3072 was always used through the handler | ||
| 7117 | interface. */ | ||
| 7118 | |||
| 7119 |
3/3✓ Branch 0 taken 3013 times.
✓ Branch 1 taken 1294 times.
✓ Branch 2 taken 1420665 times.
|
1424972 | switch (UNIV_PAGE_SIZE) { |
| 7120 | 3013 | case 4096: | |
| 7121 | 3013 | return (768); | |
| 7122 | 1294 | case 8192: | |
| 7123 | 1294 | return (1536); | |
| 7124 | 1420665 | default: | |
| 7125 | 1420665 | return (3500); | |
| 7126 | } | ||
| 7127 | } | ||
| 7128 | |||
| 7129 | /** Determines if the primary key is clustered index. | ||
| 7130 | @return true */ | ||
| 7131 | |||
| 7132 | 12320137 | bool ha_innobase::primary_key_is_clustered() const { return (true); } | |
| 7133 | |||
| 7134 | 6945530 | bool create_table_info_t::normalize_table_name(char *norm_name, | |
| 7135 | const char *name) { | ||
| 7136 | const char *name_ptr; | ||
| 7137 | ulint name_len; | ||
| 7138 | const char *db_ptr; | ||
| 7139 | ulint db_len; | ||
| 7140 | const char *ptr; | ||
| 7141 | ulint norm_len; | ||
| 7142 | |||
| 7143 | /* Scan name from the end */ | ||
| 7144 | |||
| 7145 | 6945530 | ptr = strend(name) - 1; | |
| 7146 | |||
| 7147 | /* seek to the last path separator */ | ||
| 7148 |
6/6✓ Branch 0 taken 96448894 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 96448888 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 89503367 times.
✓ Branch 5 taken 6945521 times.
|
96448908 | while (ptr >= name && *ptr != '\\' && *ptr != '/') { |
| 7149 | 89503367 | ptr--; | |
| 7150 | } | ||
| 7151 | |||
| 7152 | 6945541 | name_ptr = ptr + 1; | |
| 7153 | 6945541 | name_len = strlen(name_ptr); | |
| 7154 | |||
| 7155 | /* skip any number of path separators */ | ||
| 7156 |
5/6✓ Branch 0 taken 13891082 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13891081 times.
✓ Branch 4 taken 6945540 times.
✓ Branch 5 taken 6945541 times.
|
13891082 | while (ptr >= name && (*ptr == '\\' || *ptr == '/')) { |
| 7157 | 6945541 | ptr--; | |
| 7158 | } | ||
| 7159 | |||
| 7160 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6945541 times.
|
6945541 | assert(ptr >= name); |
| 7161 | |||
| 7162 | /* seek to the last but one path separator or one char before | ||
| 7163 | the beginning of name */ | ||
| 7164 | 6945541 | db_len = 0; | |
| 7165 |
5/6✓ Branch 0 taken 43456027 times.
✓ Branch 1 taken 210897 times.
✓ Branch 2 taken 43456039 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36721383 times.
✓ Branch 5 taken 6734656 times.
|
43666924 | while (ptr >= name && *ptr != '\\' && *ptr != '/') { |
| 7166 | 36721383 | ptr--; | |
| 7167 | 36721383 | db_len++; | |
| 7168 | } | ||
| 7169 | |||
| 7170 | 6945541 | db_ptr = ptr + 1; | |
| 7171 | |||
| 7172 | 6945541 | norm_len = db_len + name_len + sizeof "/"; | |
| 7173 | |||
| 7174 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6945541 times.
|
6945541 | if (norm_len >= FN_REFLEN - 1) { |
| 7175 | /* purecov: begin assert */ | ||
| 7176 | ✗ | ut_d(ut_error); | |
| 7177 | ut_o(return (false)); | ||
| 7178 | /* purecov: end */ | ||
| 7179 | } | ||
| 7180 | |||
| 7181 | 6945541 | memcpy(norm_name, db_ptr, db_len); | |
| 7182 | |||
| 7183 | 6945541 | norm_name[db_len] = '/'; | |
| 7184 | |||
| 7185 | /* Copy the name and null-byte. */ | ||
| 7186 | 6945541 | memcpy(norm_name + db_len + 1, name_ptr, name_len + 1); | |
| 7187 | |||
| 7188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6945541 times.
|
6945541 | if (lower_case_file_system) { |
| 7189 | ✗ | ut_ad(lower_case_table_names != 0); | |
| 7190 | ✗ | innobase_casedn_str(norm_name); | |
| 7191 | } | ||
| 7192 | 6945533 | return (true); | |
| 7193 | } | ||
| 7194 | |||
| 7195 | #ifdef UNIV_DEBUG | ||
| 7196 | /********************************************************************* | ||
| 7197 | Test normalize_table_name(). */ | ||
| 7198 | ✗ | static void test_normalize_table_name() { | |
| 7199 | char norm_name[FN_REFLEN]; | ||
| 7200 | ✗ | const char *test_data[][2] = { | |
| 7201 | /* input, expected result */ | ||
| 7202 | {"./mysqltest/t1", "mysqltest/t1"}, | ||
| 7203 | {"./test/#sql-842b_2", "test/#sql-842b_2"}, | ||
| 7204 | {"./test/#sql-85a3_10", "test/#sql-85a3_10"}, | ||
| 7205 | {"./test/#sql2-842b-2", "test/#sql2-842b-2"}, | ||
| 7206 | {"./test/bug29807", "test/bug29807"}, | ||
| 7207 | {"./test/foo", "test/foo"}, | ||
| 7208 | {"./test/innodb_bug52663", "test/innodb_bug52663"}, | ||
| 7209 | {"./test/t", "test/t"}, | ||
| 7210 | {"./test/t1", "test/t1"}, | ||
| 7211 | {"./test/t10", "test/t10"}, | ||
| 7212 | {"/a/b/db/table", "db/table"}, | ||
| 7213 | {"/a/b/db///////table", "db/table"}, | ||
| 7214 | {"/a/b////db///////table", "db/table"}, | ||
| 7215 | {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"}, | ||
| 7216 | {"db/table", "db/table"}, | ||
| 7217 | {"ddd/t", "ddd/t"}, | ||
| 7218 | {"d/ttt", "d/ttt"}, | ||
| 7219 | {"d/t", "d/t"}, | ||
| 7220 | {".\\mysqltest\\t1", "mysqltest/t1"}, | ||
| 7221 | {".\\test\\#sql-842b_2", "test/#sql-842b_2"}, | ||
| 7222 | {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"}, | ||
| 7223 | {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"}, | ||
| 7224 | {".\\test\\bug29807", "test/bug29807"}, | ||
| 7225 | {".\\test\\foo", "test/foo"}, | ||
| 7226 | {".\\test\\innodb_bug52663", "test/innodb_bug52663"}, | ||
| 7227 | {".\\test\\t", "test/t"}, | ||
| 7228 | {".\\test\\t1", "test/t1"}, | ||
| 7229 | {".\\test\\t10", "test/t10"}, | ||
| 7230 | {"C:\\a\\b\\db\\table", "db/table"}, | ||
| 7231 | {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"}, | ||
| 7232 | {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"}, | ||
| 7233 | {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"}, | ||
| 7234 | {"db\\table", "db/table"}, | ||
| 7235 | {"ddd\\t", "ddd/t"}, | ||
| 7236 | {"d\\ttt", "d/ttt"}, | ||
| 7237 | {"d\\t", "d/t"}, | ||
| 7238 | }; | ||
| 7239 | |||
| 7240 | ✗ | for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) { | |
| 7241 | ✗ | printf( | |
| 7242 | "test_normalize_table_name():" | ||
| 7243 | " testing \"%s\", expected \"%s\"... ", | ||
| 7244 | test_data[i][0], test_data[i][1]); | ||
| 7245 | |||
| 7246 | ✗ | create_table_info_t::normalize_table_name(norm_name, test_data[i][0]); | |
| 7247 | |||
| 7248 | ✗ | if (strcmp(norm_name, test_data[i][1]) == 0) { | |
| 7249 | ✗ | printf("ok\n"); | |
| 7250 | } else { | ||
| 7251 | ✗ | printf("got \"%s\"\n", norm_name); | |
| 7252 | ✗ | ut_error; | |
| 7253 | } | ||
| 7254 | } | ||
| 7255 | } | ||
| 7256 | |||
| 7257 | /********************************************************************* | ||
| 7258 | Test ut_format_name(). */ | ||
| 7259 | ✗ | static void test_ut_format_name() { | |
| 7260 | char buf[NAME_LEN * 3]; | ||
| 7261 | |||
| 7262 | struct { | ||
| 7263 | const char *name; | ||
| 7264 | ulint buf_size; | ||
| 7265 | const char *expected; | ||
| 7266 | ✗ | } test_data[] = { | |
| 7267 | {"test/t1", sizeof(buf), "`test`.`t1`"}, | ||
| 7268 | {"test/t1", 12, "`test`.`t1`"}, | ||
| 7269 | {"test/t1", 11, "`test`.`t1"}, | ||
| 7270 | {"test/t1", 10, "`test`.`t"}, | ||
| 7271 | {"test/t1", 9, "`test`.`"}, | ||
| 7272 | {"test/t1", 8, "`test`."}, | ||
| 7273 | {"test/t1", 7, "`test`"}, | ||
| 7274 | {"test/t1", 6, "`test"}, | ||
| 7275 | {"test/t1", 5, "`tes"}, | ||
| 7276 | {"test/t1", 4, "`te"}, | ||
| 7277 | {"test/t1", 3, "`t"}, | ||
| 7278 | {"test/t1", 2, "`"}, | ||
| 7279 | {"test/t1", 1, ""}, | ||
| 7280 | {"test/t1", 0, "BUF_NOT_CHANGED"}, | ||
| 7281 | {"table", sizeof(buf), "`table`"}, | ||
| 7282 | {"ta'le", sizeof(buf), "`ta'le`"}, | ||
| 7283 | {"ta\"le", sizeof(buf), "`ta\"le`"}, | ||
| 7284 | {"ta`le", sizeof(buf), "`ta``le`"}, | ||
| 7285 | }; | ||
| 7286 | |||
| 7287 | ✗ | for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) { | |
| 7288 | ✗ | memcpy(buf, "BUF_NOT_CHANGED", strlen("BUF_NOT_CHANGED") + 1); | |
| 7289 | |||
| 7290 | char *ret; | ||
| 7291 | |||
| 7292 | ✗ | ret = ut_format_name(test_data[i].name, buf, test_data[i].buf_size); | |
| 7293 | |||
| 7294 | ✗ | ut_a(ret == buf); | |
| 7295 | |||
| 7296 | ✗ | if (strcmp(buf, test_data[i].expected) == 0) { | |
| 7297 | ✗ | ib::info(ER_IB_MSG_550) << "ut_format_name(" << test_data[i].name | |
| 7298 | ✗ | << ", buf, " << test_data[i].buf_size | |
| 7299 | << ")," | ||
| 7300 | ✗ | " expected " | |
| 7301 | ✗ | << test_data[i].expected << ", OK"; | |
| 7302 | } else { | ||
| 7303 | ✗ | ib::error(ER_IB_MSG_551) | |
| 7304 | ✗ | << "ut_format_name(" << test_data[i].name << ", buf, " | |
| 7305 | ✗ | << test_data[i].buf_size | |
| 7306 | << ")," | ||
| 7307 | ✗ | " expected " | |
| 7308 | ✗ | << test_data[i].expected << ", ERROR: got " << buf; | |
| 7309 | ✗ | ut_error; | |
| 7310 | } | ||
| 7311 | } | ||
| 7312 | } | ||
| 7313 | #endif /* UNIV_DEBUG */ | ||
| 7314 | |||
| 7315 | /** Match index columns between MySQL and InnoDB. | ||
| 7316 | This function checks whether the index column information | ||
| 7317 | is consistent between KEY info from mysql and that from innodb index. | ||
| 7318 | @param[in] key_info Index info from mysql | ||
| 7319 | @param[in] index_info Index info from InnoDB | ||
| 7320 | @return true if all column types match. */ | ||
| 7321 | 4424558 | bool innobase_match_index_columns(const KEY *key_info, | |
| 7322 | const dict_index_t *index_info) { | ||
| 7323 | const KEY_PART_INFO *key_part; | ||
| 7324 | const KEY_PART_INFO *key_end; | ||
| 7325 | const dict_field_t *innodb_idx_fld; | ||
| 7326 | const dict_field_t *innodb_idx_fld_end; | ||
| 7327 | |||
| 7328 |
1/2✓ Branch 0 taken 4424558 times.
✗ Branch 1 not taken.
|
4424558 | DBUG_TRACE; |
| 7329 | |||
| 7330 | /* Check whether user defined index column count matches */ | ||
| 7331 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4424558 times.
|
4424558 | if (key_info->user_defined_key_parts != index_info->n_user_defined_cols) { |
| 7332 | ✗ | return false; | |
| 7333 | } | ||
| 7334 | |||
| 7335 | 4424558 | key_part = key_info->key_part; | |
| 7336 | 4424558 | key_end = key_part + key_info->user_defined_key_parts; | |
| 7337 | 4424558 | innodb_idx_fld = index_info->fields; | |
| 7338 | 4424558 | innodb_idx_fld_end = index_info->fields + index_info->n_fields; | |
| 7339 | |||
| 7340 | /* Check each index column's datatype. We do not check | ||
| 7341 | column name because there exists case that index | ||
| 7342 | column name got modified in mysql but such change does not | ||
| 7343 | propagate to InnoDB. | ||
| 7344 | One hidden assumption here is that the index column sequences | ||
| 7345 | are matched up between those in mysql and InnoDB. */ | ||
| 7346 |
2/2✓ Branch 0 taken 7422099 times.
✓ Branch 1 taken 4424558 times.
|
11846657 | for (; key_part != key_end; ++key_part) { |
| 7347 | ulint col_type; | ||
| 7348 | ulint is_unsigned; | ||
| 7349 | 7422099 | ulint mtype = innodb_idx_fld->col->mtype; | |
| 7350 | |||
| 7351 | /* Need to translate to InnoDB column type before | ||
| 7352 | comparison. */ | ||
| 7353 |
1/2✓ Branch 0 taken 7422099 times.
✗ Branch 1 not taken.
|
7422099 | col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field); |
| 7354 | |||
| 7355 | /* Ignore InnoDB specific system columns. */ | ||
| 7356 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7422099 times.
|
7422099 | while (mtype == DATA_SYS) { |
| 7357 | ✗ | innodb_idx_fld++; | |
| 7358 | |||
| 7359 | ✗ | if (innodb_idx_fld >= innodb_idx_fld_end) { | |
| 7360 | ✗ | return false; | |
| 7361 | } | ||
| 7362 | } | ||
| 7363 | |||
| 7364 | 7422099 | if ((bool)innodb_idx_fld->is_ascending != | |
| 7365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7422099 times.
|
7422099 | !(key_part->key_part_flag & HA_REVERSE_SORT)) { |
| 7366 | /* Column Type mismatches */ | ||
| 7367 | ✗ | return false; | |
| 7368 | } | ||
| 7369 | |||
| 7370 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7422099 times.
|
7422099 | if (col_type != mtype) { |
| 7371 | /* If the col_type we get from mysql type is a geometry | ||
| 7372 | data type, we should check if mtype is a legacy type | ||
| 7373 | from 5.6, either upgraded to DATA_GEOMETRY or not. | ||
| 7374 | This is indeed not an accurate check, but should be | ||
| 7375 | safe, since DATA_BLOB would be upgraded once we create | ||
| 7376 | spatial index on it and we intend to use DATA_GEOMETRY | ||
| 7377 | for legacy GIS data types which are of var-length. */ | ||
| 7378 | ✗ | switch (col_type) { | |
| 7379 | ✗ | case DATA_POINT: | |
| 7380 | case DATA_VAR_POINT: | ||
| 7381 | ✗ | if (DATA_POINT_MTYPE(mtype) || mtype == DATA_GEOMETRY || | |
| 7382 | mtype == DATA_BLOB) { | ||
| 7383 | ✗ | break; | |
| 7384 | } | ||
| 7385 | [[fallthrough]]; | ||
| 7386 | case DATA_GEOMETRY: | ||
| 7387 | ✗ | if (mtype == DATA_BLOB) { | |
| 7388 | ✗ | break; | |
| 7389 | } | ||
| 7390 | [[fallthrough]]; | ||
| 7391 | default: | ||
| 7392 | /* Column type mismatches */ | ||
| 7393 | ✗ | return false; | |
| 7394 | } | ||
| 7395 | } | ||
| 7396 | |||
| 7397 | 7422099 | innodb_idx_fld++; | |
| 7398 | } | ||
| 7399 | |||
| 7400 | 4424558 | return true; | |
| 7401 | 4424558 | } | |
| 7402 | |||
| 7403 | /** Build a template for a base column for a virtual column | ||
| 7404 | @param[in] table MySQL TABLE | ||
| 7405 | @param[in] clust_index InnoDB clustered index | ||
| 7406 | @param[in] field field in MySQL table | ||
| 7407 | @param[in] col InnoDB column | ||
| 7408 | @param[in,out] templ template to fill | ||
| 7409 | @param[in] col_no field index for virtual col | ||
| 7410 | */ | ||
| 7411 | 115811 | static void innobase_vcol_build_templ(const TABLE *table, | |
| 7412 | const dict_index_t *clust_index, | ||
| 7413 | Field *field, const dict_col_t *col, | ||
| 7414 | mysql_row_templ_t *templ, ulint col_no) { | ||
| 7415 |
2/2✓ Branch 0 taken 61617 times.
✓ Branch 1 taken 54194 times.
|
115811 | if (col->is_virtual()) { |
| 7416 | 61617 | templ->is_virtual = true; | |
| 7417 | 61617 | templ->col_no = col_no; | |
| 7418 | 61617 | templ->clust_rec_field_no = ULINT_UNDEFINED; | |
| 7419 | 61617 | templ->rec_field_no = col->ind; | |
| 7420 | } else { | ||
| 7421 | 54194 | templ->is_virtual = false; | |
| 7422 | 54194 | templ->col_no = col_no; | |
| 7423 | 54194 | templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index); | |
| 7424 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54194 times.
|
54194 | ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED); |
| 7425 | |||
| 7426 | 54194 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 7427 | } | ||
| 7428 | |||
| 7429 | 115811 | templ->icp_rec_field_no = ULINT_UNDEFINED; | |
| 7430 | |||
| 7431 |
2/2✓ Branch 0 taken 62561 times.
✓ Branch 1 taken 53250 times.
|
115811 | if (field->is_nullable()) { |
| 7432 | 62561 | templ->mysql_null_byte_offset = field->null_offset(); | |
| 7433 | |||
| 7434 | 62561 | templ->mysql_null_bit_mask = (ulint)field->null_bit; | |
| 7435 | } else { | ||
| 7436 | 53250 | templ->mysql_null_bit_mask = 0; | |
| 7437 | } | ||
| 7438 | |||
| 7439 | 115811 | templ->mysql_col_offset = static_cast<ulint>(get_field_offset(table, field)); | |
| 7440 | 115811 | templ->mysql_col_len = static_cast<ulint>(field->pack_length()); | |
| 7441 | /* The multi-value index indexes attribute values in a JSON doc, so its | ||
| 7442 | index field length could be different from the actual column data length */ | ||
| 7443 |
6/6✓ Branch 0 taken 61617 times.
✓ Branch 1 taken 54194 times.
✓ Branch 2 taken 577 times.
✓ Branch 3 taken 61040 times.
✓ Branch 4 taken 577 times.
✓ Branch 5 taken 115234 times.
|
115811 | if (templ->is_virtual && innobase_is_multi_value_fld(field)) { |
| 7444 | 577 | templ->mysql_mvidx_len = static_cast<ulint>(field->key_length()); | |
| 7445 | 577 | templ->is_multi_val = true; | |
| 7446 | } else { | ||
| 7447 | 115234 | templ->mysql_mvidx_len = 0; | |
| 7448 | 115234 | templ->is_multi_val = false; | |
| 7449 | } | ||
| 7450 | |||
| 7451 | 115811 | templ->type = col->mtype; | |
| 7452 | 115811 | templ->mysql_type = static_cast<ulint>(field->type()); | |
| 7453 | |||
| 7454 |
2/2✓ Branch 0 taken 50292 times.
✓ Branch 1 taken 65519 times.
|
115811 | if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { |
| 7455 | 50292 | templ->mysql_length_bytes = field->get_length_bytes(); | |
| 7456 | } | ||
| 7457 | |||
| 7458 | 115811 | templ->charset = dtype_get_charset_coll(col->prtype); | |
| 7459 | 115811 | templ->mbminlen = col->get_mbminlen(); | |
| 7460 | 115811 | templ->mbmaxlen = col->get_mbmaxlen(); | |
| 7461 | 115811 | templ->is_unsigned = col->prtype & DATA_UNSIGNED; | |
| 7462 | 115811 | templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED); | |
| 7463 | 115811 | templ->zip_dict_data = field->zip_dict_data; | |
| 7464 | 115811 | } | |
| 7465 | |||
| 7466 | /** Callback used by MySQL server layer to initialize | ||
| 7467 | the table virtual columns' template | ||
| 7468 | @param[in] table MySQL TABLE | ||
| 7469 | @param[in,out] ib_table InnoDB table */ | ||
| 7470 | 1 | void innobase_build_v_templ_callback(const TABLE *table, void *ib_table) { | |
| 7471 | 1 | const dict_table_t *t_table = static_cast<dict_table_t *>(ib_table); | |
| 7472 | |||
| 7473 | 1 | innobase_build_v_templ(table, t_table, t_table->vc_templ, nullptr, true, | |
| 7474 | nullptr); | ||
| 7475 | 1 | } | |
| 7476 | |||
| 7477 | /** Build template for the virtual columns and their base columns. This | ||
| 7478 | is done when the table first opened. | ||
| 7479 | @param[in] table MySQL TABLE | ||
| 7480 | @param[in] ib_table InnoDB dict_table_t | ||
| 7481 | @param[in,out] s_templ InnoDB template structure | ||
| 7482 | @param[in] add_v new virtual columns added along with | ||
| 7483 | add index call | ||
| 7484 | @param[in] locked true if dict_sys mutex is held | ||
| 7485 | @param[in] share_tbl_name original MySQL table name */ | ||
| 7486 | 54246 | void innobase_build_v_templ(const TABLE *table, const dict_table_t *ib_table, | |
| 7487 | dict_vcol_templ_t *s_templ, | ||
| 7488 | const dict_add_v_col_t *add_v, bool locked, | ||
| 7489 | const char *share_tbl_name) { | ||
| 7490 | 54246 | ulint ncol = ib_table->n_cols - DATA_N_SYS_COLS; | |
| 7491 | 54246 | ulint n_v_col = ib_table->n_v_cols; | |
| 7492 | bool marker[REC_MAX_N_FIELDS]; | ||
| 7493 | |||
| 7494 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54246 times.
|
54246 | ut_ad(ncol < REC_MAX_N_FIELDS); |
| 7495 | |||
| 7496 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 54078 times.
|
54246 | if (add_v != nullptr) { |
| 7497 | 168 | n_v_col += add_v->n_v_col; | |
| 7498 | } | ||
| 7499 | |||
| 7500 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54246 times.
|
54246 | ut_ad(n_v_col > 0); |
| 7501 | |||
| 7502 |
2/2✓ Branch 0 taken 991 times.
✓ Branch 1 taken 53255 times.
|
54246 | if (!locked) { |
| 7503 |
1/2✓ Branch 0 taken 991 times.
✗ Branch 1 not taken.
|
991 | dict_sys_mutex_enter(); |
| 7504 | } | ||
| 7505 | |||
| 7506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54246 times.
|
54246 | if (s_templ->vtempl) { |
| 7507 | ✗ | if (!locked) { | |
| 7508 | ✗ | dict_sys_mutex_exit(); | |
| 7509 | } | ||
| 7510 | ✗ | return; | |
| 7511 | } | ||
| 7512 | |||
| 7513 | 54246 | memset(marker, 0, sizeof(bool) * ncol); | |
| 7514 | |||
| 7515 | 54246 | s_templ->vtempl = static_cast<mysql_row_templ_t **>(ut::zalloc_withkey( | |
| 7516 | 54246 | UT_NEW_THIS_FILE_PSI_KEY, (ncol + n_v_col) * sizeof *s_templ->vtempl)); | |
| 7517 | 54246 | s_templ->n_col = ncol; | |
| 7518 | 54246 | s_templ->n_v_col = n_v_col; | |
| 7519 | 54246 | s_templ->rec_len = table->s->reclength; | |
| 7520 | 54246 | s_templ->default_rec = static_cast<byte *>( | |
| 7521 | 54246 | ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, table->s->reclength)); | |
| 7522 | 54246 | memcpy(s_templ->default_rec, table->s->default_values, table->s->reclength); | |
| 7523 | |||
| 7524 | /* Mark those columns could be base columns */ | ||
| 7525 |
2/2✓ Branch 0 taken 61436 times.
✓ Branch 1 taken 54246 times.
|
115682 | for (ulint i = 0; i < ib_table->n_v_cols; i++) { |
| 7526 |
1/2✓ Branch 0 taken 61436 times.
✗ Branch 1 not taken.
|
61436 | const dict_v_col_t *vcol = dict_table_get_nth_v_col(ib_table, i); |
| 7527 | |||
| 7528 |
2/2✓ Branch 0 taken 60364 times.
✓ Branch 1 taken 61436 times.
|
121800 | for (ulint j = 0; j < vcol->num_base; j++) { |
| 7529 | 60364 | ulint col_no = vcol->base_col[j]->ind; | |
| 7530 | 60364 | marker[col_no] = true; | |
| 7531 | } | ||
| 7532 | } | ||
| 7533 | |||
| 7534 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 54078 times.
|
54246 | if (add_v) { |
| 7535 |
2/2✓ Branch 0 taken 181 times.
✓ Branch 1 taken 168 times.
|
349 | for (ulint i = 0; i < add_v->n_v_col; i++) { |
| 7536 | 181 | const dict_v_col_t *vcol = &add_v->v_col[i]; | |
| 7537 | |||
| 7538 |
2/2✓ Branch 0 taken 218 times.
✓ Branch 1 taken 181 times.
|
399 | for (ulint j = 0; j < vcol->num_base; j++) { |
| 7539 | 218 | ulint col_no = vcol->base_col[j]->ind; | |
| 7540 | 218 | marker[col_no] = true; | |
| 7541 | } | ||
| 7542 | } | ||
| 7543 | } | ||
| 7544 | |||
| 7545 | 54246 | ulint j = 0; | |
| 7546 | 54246 | ulint z = 0; | |
| 7547 | |||
| 7548 |
1/2✓ Branch 0 taken 54246 times.
✗ Branch 1 not taken.
|
54246 | const dict_index_t *clust_index = ib_table->first_index(); |
| 7549 | |||
| 7550 |
2/2✓ Branch 0 taken 323627 times.
✓ Branch 1 taken 54246 times.
|
377873 | for (ulint i = 0; i < table->s->fields; i++) { |
| 7551 | 323627 | Field *field = table->field[i]; | |
| 7552 | |||
| 7553 | /* Build template for virtual columns */ | ||
| 7554 |
4/4✓ Branch 0 taken 64871 times.
✓ Branch 1 taken 258756 times.
✓ Branch 2 taken 61617 times.
✓ Branch 3 taken 3254 times.
|
323627 | if (innobase_is_v_fld(field)) { |
| 7555 | #ifdef UNIV_DEBUG | ||
| 7556 | const char *name; | ||
| 7557 | |||
| 7558 |
2/2✓ Branch 0 taken 181 times.
✓ Branch 1 taken 61436 times.
|
61617 | if (z >= ib_table->n_v_def) { |
| 7559 | 181 | name = add_v->v_col_name[z - ib_table->n_v_def]; | |
| 7560 | } else { | ||
| 7561 |
1/2✓ Branch 0 taken 61436 times.
✗ Branch 1 not taken.
|
61436 | name = dict_table_get_v_col_name(ib_table, z); |
| 7562 | } | ||
| 7563 | |||
| 7564 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61617 times.
|
61617 | ut_ad(!ut_strcmp(name, field->field_name)); |
| 7565 | #endif | ||
| 7566 | const dict_v_col_t *vcol; | ||
| 7567 | |||
| 7568 |
2/2✓ Branch 0 taken 181 times.
✓ Branch 1 taken 61436 times.
|
61617 | if (z >= ib_table->n_v_def) { |
| 7569 | 181 | vcol = &add_v->v_col[z - ib_table->n_v_def]; | |
| 7570 | } else { | ||
| 7571 |
1/2✓ Branch 0 taken 61436 times.
✗ Branch 1 not taken.
|
61436 | vcol = dict_table_get_nth_v_col(ib_table, z); |
| 7572 | } | ||
| 7573 | |||
| 7574 | 123234 | s_templ->vtempl[z + s_templ->n_col] = | |
| 7575 | 61617 | static_cast<mysql_row_templ_t *>(ut::malloc_withkey( | |
| 7576 | 61617 | UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j])); | |
| 7577 | |||
| 7578 | 61617 | innobase_vcol_build_templ(table, clust_index, field, &vcol->m_col, | |
| 7579 |
1/2✓ Branch 0 taken 61617 times.
✗ Branch 1 not taken.
|
61617 | s_templ->vtempl[z + s_templ->n_col], z); |
| 7580 | 61617 | z++; | |
| 7581 | 61617 | continue; | |
| 7582 | 61617 | } | |
| 7583 | |||
| 7584 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 262010 times.
|
262010 | ut_ad(j < ncol); |
| 7585 | |||
| 7586 | /* Build template for base columns */ | ||
| 7587 |
2/2✓ Branch 0 taken 54194 times.
✓ Branch 1 taken 207816 times.
|
262010 | if (marker[j]) { |
| 7588 |
1/2✓ Branch 0 taken 54194 times.
✗ Branch 1 not taken.
|
54194 | dict_col_t *col = ib_table->get_col(j); |
| 7589 | |||
| 7590 | #ifdef UNIV_DEBUG | ||
| 7591 |
1/2✓ Branch 0 taken 54194 times.
✗ Branch 1 not taken.
|
54194 | const char *name = ib_table->get_col_name(j); |
| 7592 | |||
| 7593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54194 times.
|
54194 | ut_ad(!ut_strcmp(name, field->field_name)); |
| 7594 | #endif | ||
| 7595 | |||
| 7596 | 54194 | s_templ->vtempl[j] = static_cast<mysql_row_templ_t *>(ut::malloc_withkey( | |
| 7597 | 54194 | UT_NEW_THIS_FILE_PSI_KEY, sizeof *s_templ->vtempl[j])); | |
| 7598 | |||
| 7599 | 54194 | innobase_vcol_build_templ(table, clust_index, field, col, | |
| 7600 |
1/2✓ Branch 0 taken 54194 times.
✗ Branch 1 not taken.
|
54194 | s_templ->vtempl[j], j); |
| 7601 | } | ||
| 7602 | |||
| 7603 | 262010 | j++; | |
| 7604 | } | ||
| 7605 | |||
| 7606 |
2/2✓ Branch 0 taken 991 times.
✓ Branch 1 taken 53255 times.
|
54246 | if (!locked) { |
| 7607 |
1/2✓ Branch 0 taken 991 times.
✗ Branch 1 not taken.
|
991 | dict_sys_mutex_exit(); |
| 7608 | } | ||
| 7609 | |||
| 7610 |
1/2✓ Branch 0 taken 54246 times.
✗ Branch 1 not taken.
|
54246 | s_templ->db_name = table->s->db.str; |
| 7611 |
1/2✓ Branch 0 taken 54246 times.
✗ Branch 1 not taken.
|
54246 | s_templ->tb_name = table->s->table_name.str; |
| 7612 | |||
| 7613 |
2/2✓ Branch 0 taken 52434 times.
✓ Branch 1 taken 1812 times.
|
54246 | if (share_tbl_name) { |
| 7614 |
1/2✓ Branch 0 taken 52434 times.
✗ Branch 1 not taken.
|
52434 | s_templ->share_name = share_tbl_name; |
| 7615 | } | ||
| 7616 | } | ||
| 7617 | |||
| 7618 | /** This function builds a translation table in INNOBASE_SHARE | ||
| 7619 | structure for fast index location with mysql array number from its | ||
| 7620 | table->key_info structure. This also provides the necessary translation | ||
| 7621 | between the key order in mysql key_info and InnoDB ib_table->indexes if | ||
| 7622 | they are not fully matched with each other. | ||
| 7623 | Note we do not have any mutex protecting the translation table | ||
| 7624 | building based on the assumption that there is no concurrent | ||
| 7625 | index creation/drop and DMLs that requires index lookup. All table | ||
| 7626 | handle will be closed before the index creation/drop. | ||
| 7627 | @return true if index translation table built successfully */ | ||
| 7628 | 4556680 | bool innobase_build_index_translation( | |
| 7629 | const TABLE *table, /*!< in: table in MySQL data | ||
| 7630 | dictionary */ | ||
| 7631 | dict_table_t *ib_table, /*!< in: table in InnoDB data | ||
| 7632 | dictionary */ | ||
| 7633 | INNOBASE_SHARE *share) /*!< in/out: share structure | ||
| 7634 | where index translation table | ||
| 7635 | will be constructed in. */ | ||
| 7636 | { | ||
| 7637 |
1/2✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
|
4556680 | DBUG_TRACE; |
| 7638 | |||
| 7639 | 4556683 | bool ret = true; | |
| 7640 | |||
| 7641 |
1/2✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
|
4556683 | dict_sys_mutex_enter(); |
| 7642 | |||
| 7643 | 4556683 | ulint mysql_num_index = table->s->keys; | |
| 7644 |
1/2✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
|
4556683 | ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes); |
| 7645 | 4556683 | dict_index_t **index_mapping = share->idx_trans_tbl.index_mapping; | |
| 7646 | |||
| 7647 | /* If there exists inconsistency between MySQL and InnoDB dictionary | ||
| 7648 | (metadata) information, the number of index defined in MySQL | ||
| 7649 | could exceed that in InnoDB, do not build index translation | ||
| 7650 | table in such case */ | ||
| 7651 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4556683 times.
|
4556683 | if (ib_num_index < mysql_num_index) { |
| 7652 | ✗ | ret = false; | |
| 7653 | ✗ | goto func_exit; | |
| 7654 | } | ||
| 7655 | |||
| 7656 | /* If index entry count is non-zero, nothing has | ||
| 7657 | changed since last update, directly return true */ | ||
| 7658 |
2/2✓ Branch 0 taken 2349848 times.
✓ Branch 1 taken 2206835 times.
|
4556683 | if (share->idx_trans_tbl.index_count) { |
| 7659 | /* Index entry count should still match mysql_num_index */ | ||
| 7660 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2349848 times.
|
2349848 | ut_a(share->idx_trans_tbl.index_count == mysql_num_index); |
| 7661 | 2349848 | goto func_exit; | |
| 7662 | } | ||
| 7663 | |||
| 7664 | /* The number of index increased, rebuild the mapping table */ | ||
| 7665 |
2/2✓ Branch 0 taken 1743389 times.
✓ Branch 1 taken 463446 times.
|
2206835 | if (mysql_num_index > share->idx_trans_tbl.array_size) { |
| 7666 | index_mapping = reinterpret_cast<dict_index_t **>( | ||
| 7667 | 1743389 | ut::realloc_withkey(UT_NEW_THIS_FILE_PSI_KEY, index_mapping, | |
| 7668 | mysql_num_index * sizeof(*index_mapping))); | ||
| 7669 | |||
| 7670 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1743389 times.
|
1743389 | if (index_mapping == nullptr) { |
| 7671 | /* Report an error if index_mapping continues to be | ||
| 7672 | NULL and mysql_num_index is a non-zero value */ | ||
| 7673 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_TRX_XLATION_TABLE_OOM, mysql_num_index, | |
| 7674 | share->idx_trans_tbl.array_size); | ||
| 7675 | ✗ | ret = false; | |
| 7676 | ✗ | goto func_exit; | |
| 7677 | } | ||
| 7678 | |||
| 7679 | 1743389 | share->idx_trans_tbl.array_size = mysql_num_index; | |
| 7680 | } | ||
| 7681 | |||
| 7682 | /* For each index in the mysql key_info array, fetch its | ||
| 7683 | corresponding InnoDB index pointer into index_mapping | ||
| 7684 | array. */ | ||
| 7685 |
2/2✓ Branch 0 taken 4392113 times.
✓ Branch 1 taken 2206835 times.
|
6598948 | for (ulint count = 0; count < mysql_num_index; count++) { |
| 7686 | /* Fetch index pointers into index_mapping according to mysql | ||
| 7687 | index sequence */ | ||
| 7688 | 8784226 | index_mapping[count] = | |
| 7689 |
1/2✓ Branch 0 taken 4392113 times.
✗ Branch 1 not taken.
|
4392113 | dict_table_get_index_on_name(ib_table, table->key_info[count].name); |
| 7690 | |||
| 7691 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4392113 times.
|
4392113 | if (index_mapping[count] == nullptr) { |
| 7692 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_CANT_FIND_INDEX_IN_INNODB_DD, | |
| 7693 | table->key_info[count].name); | ||
| 7694 | ✗ | ret = false; | |
| 7695 | ✗ | goto func_exit; | |
| 7696 | } | ||
| 7697 | |||
| 7698 | /* Double check fetched index has the same | ||
| 7699 | column info as those in mysql key_info. */ | ||
| 7700 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4392113 times.
|
4392113 | if (!innobase_match_index_columns(&table->key_info[count], |
| 7701 |
1/2✓ Branch 0 taken 4392113 times.
✗ Branch 1 not taken.
|
4392113 | index_mapping[count])) { |
| 7702 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_INDEX_COLUMN_INFO_UNLIKE_MYSQLS, | |
| 7703 | table->key_info[count].name); | ||
| 7704 | ✗ | ret = false; | |
| 7705 | ✗ | goto func_exit; | |
| 7706 | } | ||
| 7707 | } | ||
| 7708 | |||
| 7709 | /* Successfully built the translation table */ | ||
| 7710 | 2206835 | share->idx_trans_tbl.index_count = mysql_num_index; | |
| 7711 | |||
| 7712 | 4556683 | func_exit: | |
| 7713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4556683 times.
|
4556683 | if (!ret) { |
| 7714 | /* Build translation table failed. */ | ||
| 7715 | ✗ | ut::free(index_mapping); | |
| 7716 | |||
| 7717 | ✗ | share->idx_trans_tbl.array_size = 0; | |
| 7718 | ✗ | share->idx_trans_tbl.index_count = 0; | |
| 7719 | ✗ | index_mapping = nullptr; | |
| 7720 | } | ||
| 7721 | |||
| 7722 | 4556683 | share->idx_trans_tbl.index_mapping = index_mapping; | |
| 7723 | |||
| 7724 |
1/2✓ Branch 0 taken 4556683 times.
✗ Branch 1 not taken.
|
4556683 | dict_sys_mutex_exit(); |
| 7725 | |||
| 7726 | 4556683 | return ret; | |
| 7727 | 4556683 | } | |
| 7728 | |||
| 7729 | /** This function uses index translation table to quickly locate the | ||
| 7730 | requested index structure. | ||
| 7731 | Note we do not have mutex protection for the index translatoin table | ||
| 7732 | access, it is based on the assumption that there is no concurrent | ||
| 7733 | translation table rebuild (fter create/drop index) and DMLs that | ||
| 7734 | require index lookup. | ||
| 7735 | @return dict_index_t structure for requested index. NULL if | ||
| 7736 | fail to locate the index structure. */ | ||
| 7737 | 131401507 | static dict_index_t *innobase_index_lookup( | |
| 7738 | INNOBASE_SHARE *share, /*!< in: share structure for index | ||
| 7739 | translation table. */ | ||
| 7740 | uint keynr) /*!< in: index number for the requested | ||
| 7741 | index */ | ||
| 7742 | { | ||
| 7743 |
1/2✓ Branch 0 taken 131401588 times.
✗ Branch 1 not taken.
|
131401507 | if (share->idx_trans_tbl.index_mapping == nullptr || |
| 7744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 131401661 times.
|
131401588 | keynr >= share->idx_trans_tbl.index_count) { |
| 7745 | ✗ | return (nullptr); | |
| 7746 | } | ||
| 7747 | |||
| 7748 | 131401661 | return (share->idx_trans_tbl.index_mapping[keynr]); | |
| 7749 | } | ||
| 7750 | |||
| 7751 | /** Set the autoinc column max value. This should only be called from | ||
| 7752 | ha_innobase::open, therefore there's no need for a covering lock. */ | ||
| 7753 | 126630 | void ha_innobase::innobase_initialize_autoinc() { | |
| 7754 | ulonglong auto_inc; | ||
| 7755 | 126630 | const Field *field = table->found_next_number_field; | |
| 7756 | |||
| 7757 |
1/2✓ Branch 0 taken 126630 times.
✗ Branch 1 not taken.
|
126630 | if (field != nullptr) { |
| 7758 | 126630 | auto_inc = field->get_max_int_value(); | |
| 7759 | |||
| 7760 | /* autoinc column cannot be virtual column */ | ||
| 7761 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 126630 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 126630 times.
|
126630 | ut_ad(!innobase_is_v_fld(field)); |
| 7762 | } else { | ||
| 7763 | /* We have no idea what's been passed in to us as the | ||
| 7764 | autoinc column. We set it to the 0, effectively disabling | ||
| 7765 | updates to the table. */ | ||
| 7766 | ✗ | auto_inc = 0; | |
| 7767 | |||
| 7768 | ✗ | ib::info(ER_IB_MSG_552) << "Unable to determine the AUTOINC column name"; | |
| 7769 | } | ||
| 7770 | |||
| 7771 |
2/2✓ Branch 0 taken 94 times.
✓ Branch 1 taken 126536 times.
|
126630 | if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { |
| 7772 | /* If the recovery level is set so high that writes | ||
| 7773 | are disabled we force the AUTOINC counter to 0 | ||
| 7774 | value effectively disabling writes to the table. | ||
| 7775 | Secondly, we avoid reading the table in case the read | ||
| 7776 | results in failure due to a corrupted table/index. | ||
| 7777 | |||
| 7778 | We will not return an error to the client, so that the | ||
| 7779 | tables can be dumped with minimal hassle. If an error | ||
| 7780 | were returned in this case, the first attempt to read | ||
| 7781 | the table would fail and subsequent SELECTs would succeed. */ | ||
| 7782 | 94 | auto_inc = 0; | |
| 7783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 126536 times.
|
126536 | } else if (field == nullptr) { |
| 7784 | /* This is a far more serious error, best to avoid | ||
| 7785 | opening the table and return failure. */ | ||
| 7786 | ✗ | my_error(ER_AUTOINC_READ_FAILED, MYF(0)); | |
| 7787 | } else { | ||
| 7788 | 126536 | dict_index_t *index = nullptr; | |
| 7789 | const char *col_name; | ||
| 7790 | uint64_t read_auto_inc; | ||
| 7791 | ulint err; | ||
| 7792 | |||
| 7793 |
2/4✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126536 times.
✗ Branch 3 not taken.
|
126536 | update_thd(ha_thd()); |
| 7794 | |||
| 7795 | 126536 | col_name = field->field_name; | |
| 7796 | |||
| 7797 |
1/2✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
|
126536 | read_auto_inc = dict_table_autoinc_read(m_prebuilt->table); |
| 7798 | |||
| 7799 |
2/2✓ Branch 0 taken 25727 times.
✓ Branch 1 taken 100809 times.
|
126536 | if (read_auto_inc == 0) { |
| 7800 |
1/2✓ Branch 0 taken 25727 times.
✗ Branch 1 not taken.
|
25727 | index = innobase_get_index(table->s->next_number_index); |
| 7801 | |||
| 7802 | /* Execute SELECT MAX(col_name) FROM TABLE; | ||
| 7803 | This is necessary when an imported tablespace | ||
| 7804 | doesn't have a correct cfg file so autoinc | ||
| 7805 | has not been initialized, or the table is empty. */ | ||
| 7806 |
1/2✓ Branch 0 taken 25727 times.
✗ Branch 1 not taken.
|
25727 | err = row_search_max_autoinc(index, col_name, &read_auto_inc); |
| 7807 | |||
| 7808 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25727 times.
|
25727 | if (read_auto_inc > 0) { |
| 7809 | ✗ | ib::warn(ER_IB_MSG_553) | |
| 7810 | ✗ | << "Reading max(auto_inc_col) = " << read_auto_inc << " for table " | |
| 7811 | ✗ | << index->table->name << ", because there was an IMPORT" | |
| 7812 | ✗ | << " without cfg file."; | |
| 7813 | } | ||
| 7814 | |||
| 7815 | } else { | ||
| 7816 | 100809 | err = DB_SUCCESS; | |
| 7817 | } | ||
| 7818 | |||
| 7819 |
1/3✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
126536 | switch (err) { |
| 7820 | 126536 | case DB_SUCCESS: { | |
| 7821 | ulonglong col_max_value; | ||
| 7822 | |||
| 7823 |
1/2✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
|
126536 | col_max_value = field->get_max_int_value(); |
| 7824 | |||
| 7825 | /* At the this stage we do not know the increment | ||
| 7826 | nor the offset, so use a default increment of 1. */ | ||
| 7827 | |||
| 7828 |
1/2✓ Branch 0 taken 126536 times.
✗ Branch 1 not taken.
|
126536 | auto_inc = innobase_next_autoinc(read_auto_inc, 1, 1, 0, col_max_value); |
| 7829 | |||
| 7830 | 126536 | break; | |
| 7831 | } | ||
| 7832 | ✗ | case DB_RECORD_NOT_FOUND: | |
| 7833 | ✗ | ib::error(ER_IB_MSG_554) << "MySQL and InnoDB data dictionaries are" | |
| 7834 | " out of sync. Unable to find the AUTOINC" | ||
| 7835 | ✗ | " column " | |
| 7836 | ✗ | << col_name | |
| 7837 | << " in the InnoDB" | ||
| 7838 | ✗ | " table " | |
| 7839 | ✗ | << index->table->name | |
| 7840 | << ". We set" | ||
| 7841 | " the next AUTOINC column value to 0, in" | ||
| 7842 | " effect disabling the AUTOINC next value" | ||
| 7843 | ✗ | " generation."; | |
| 7844 | |||
| 7845 | ✗ | ib::info(ER_IB_MSG_555) << "You can either set the next AUTOINC" | |
| 7846 | " value explicitly using ALTER TABLE or fix" | ||
| 7847 | " the data dictionary by recreating the" | ||
| 7848 | ✗ | " table."; | |
| 7849 | |||
| 7850 | /* This will disable the AUTOINC generation. */ | ||
| 7851 | ✗ | auto_inc = 0; | |
| 7852 | |||
| 7853 | /* We want the open to succeed, so that the user can | ||
| 7854 | take corrective action. ie. reads should succeed but | ||
| 7855 | updates should fail. */ | ||
| 7856 | ✗ | err = DB_SUCCESS; | |
| 7857 | ✗ | break; | |
| 7858 | ✗ | default: | |
| 7859 | /* row_search_max_autoinc() should only return | ||
| 7860 | one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */ | ||
| 7861 | ✗ | ut_error; | |
| 7862 | } | ||
| 7863 | } | ||
| 7864 | |||
| 7865 | 126630 | dict_table_autoinc_initialize(m_prebuilt->table, auto_inc); | |
| 7866 | 126630 | } | |
| 7867 | |||
| 7868 | /** Open an InnoDB table. | ||
| 7869 | @param[in] name table name | ||
| 7870 | @param[in] open_flags flags for opening table from SQL-layer. | ||
| 7871 | @param[in] table_def dd::Table object describing table to be opened | ||
| 7872 | @retval 1 if error | ||
| 7873 | @retval 0 if success */ | ||
| 7874 | 4556991 | int ha_innobase::open(const char *name, int, uint open_flags, | |
| 7875 | const dd::Table *table_def) { | ||
| 7876 | dict_table_t *ib_table; | ||
| 7877 | char norm_name[FN_REFLEN]; | ||
| 7878 | THD *thd; | ||
| 7879 | 4556991 | bool cached = false; | |
| 7880 | |||
| 7881 |
1/2✓ Branch 0 taken 4557001 times.
✗ Branch 1 not taken.
|
4556991 | DBUG_TRACE; |
| 7882 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4557001 times.
|
4557001 | assert(table_share == table->s); |
| 7883 | |||
| 7884 |
1/2✓ Branch 0 taken 4556999 times.
✗ Branch 1 not taken.
|
4557001 | thd = ha_thd(); |
| 7885 | |||
| 7886 |
2/4✓ Branch 0 taken 4556993 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556993 times.
|
4556999 | if (!normalize_table_name(norm_name, name)) { |
| 7887 | /* purecov: begin inspected */ | ||
| 7888 | ✗ | ut_d(ut_error); | |
| 7889 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 7890 | /* purecov: end */ | ||
| 7891 | } | ||
| 7892 | |||
| 7893 | 4556993 | m_user_thd = nullptr; | |
| 7894 | 4556993 | m_share = nullptr; | |
| 7895 | |||
| 7896 | /* Will be allocated if it is needed in ::update_row() */ | ||
| 7897 | 4556993 | m_upd_buf = nullptr; | |
| 7898 | 4556993 | m_upd_buf_size = 0; | |
| 7899 | |||
| 7900 | /* Get pointer to a table object in InnoDB dictionary cache. | ||
| 7901 | For intrinsic table, get it from session private data */ | ||
| 7902 |
2/4✓ Branch 0 taken 4557001 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556999 times.
✗ Branch 3 not taken.
|
4556993 | ib_table = thd_to_innodb_session(thd)->lookup_table_handler(norm_name); |
| 7903 | |||
| 7904 |
2/2✓ Branch 0 taken 4374131 times.
✓ Branch 1 taken 182868 times.
|
4556999 | if (ib_table == nullptr) { |
| 7905 |
3/4✓ Branch 0 taken 4284328 times.
✓ Branch 1 taken 89803 times.
✓ Branch 2 taken 4284331 times.
✗ Branch 3 not taken.
|
4374131 | DEBUG_SYNC_C("ha_innobase_open"); |
| 7906 | |||
| 7907 |
1/2✓ Branch 0 taken 4374135 times.
✗ Branch 1 not taken.
|
4374134 | dict_sys_mutex_enter(); |
| 7908 |
1/2✓ Branch 0 taken 4374135 times.
✗ Branch 1 not taken.
|
4374135 | ib_table = dict_table_check_if_in_cache_low(norm_name); |
| 7909 |
2/2✓ Branch 0 taken 3491293 times.
✓ Branch 1 taken 882842 times.
|
4374135 | if (ib_table != nullptr) { |
| 7910 |
3/4✓ Branch 0 taken 3491293 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3491291 times.
|
3491293 | if (ib_table->is_corrupted()) { |
| 7911 | /* Optionally remove this corrupted table from cache now | ||
| 7912 | if no other thread is still using it. If not, the corrupted bit | ||
| 7913 | will keep it from being used.*/ | ||
| 7914 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (ib_table->get_ref_count() == 0) { |
| 7915 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_table_remove_from_cache(ib_table); |
| 7916 | } | ||
| 7917 | 2 | ib_table = nullptr; | |
| 7918 | 2 | cached = true; | |
| 7919 |
2/2✓ Branch 0 taken 6560 times.
✓ Branch 1 taken 3484731 times.
|
3491291 | } else if (ib_table->refresh_fk) { |
| 7920 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | ib_table->acquire_with_lock(); |
| 7921 | |||
| 7922 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | dict_names_t fk_tables; |
| 7923 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | dict_sys_mutex_exit(); |
| 7924 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 7925 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 7926 | |||
| 7927 | 19680 | dberr_t err = dd_table_load_fk( | |
| 7928 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | client, ib_table->name.m_name, nullptr, ib_table, |
| 7929 | 6560 | &table_def->table(), thd, false, | |
| 7930 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | !thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS), &fk_tables); |
| 7931 | |||
| 7932 |
1/2✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
|
6560 | dict_sys_mutex_enter(); |
| 7933 | 6560 | ib_table->refresh_fk = false; | |
| 7934 | |||
| 7935 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6560 times.
|
6560 | if (err != DB_SUCCESS) { |
| 7936 | ✗ | ib_table->release(); | |
| 7937 | ✗ | goto reload; | |
| 7938 | } | ||
| 7939 | |||
| 7940 | 6560 | cached = true; | |
| 7941 |
4/6✓ Branch 0 taken 6560 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6560 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28838 times.
✓ Branch 5 taken 3455893 times.
|
3491291 | } else if (ib_table->discard_after_ddl) { |
| 7942 | 28838 | reload: | |
| 7943 |
1/2✓ Branch 0 taken 28838 times.
✗ Branch 1 not taken.
|
28838 | btr_drop_ahi_for_table(ib_table); |
| 7944 |
1/2✓ Branch 0 taken 28838 times.
✗ Branch 1 not taken.
|
28838 | dict_table_remove_from_cache(ib_table); |
| 7945 | 28838 | ib_table = nullptr; | |
| 7946 | } else { | ||
| 7947 | 3455893 | cached = true; | |
| 7948 |
2/4✓ Branch 0 taken 3455893 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3455893 times.
|
3455893 | if (!dd_table_match(ib_table, table_def)) { |
| 7949 | ✗ | dict_set_corrupted(ib_table->first_index()); | |
| 7950 | ✗ | dict_table_remove_from_cache(ib_table); | |
| 7951 | ✗ | ib_table = nullptr; | |
| 7952 | } else { | ||
| 7953 |
1/2✓ Branch 0 taken 3455893 times.
✗ Branch 1 not taken.
|
3455893 | ib_table->acquire_with_lock(); |
| 7954 | } | ||
| 7955 | } | ||
| 7956 | |||
| 7957 | /* If the table is in-memory, always get the latest | ||
| 7958 | version, in case this is open table after DDL */ | ||
| 7959 |
4/4✓ Branch 0 taken 3462453 times.
✓ Branch 1 taken 28840 times.
✓ Branch 2 taken 3263178 times.
✓ Branch 3 taken 199275 times.
|
3491293 | if (ib_table != nullptr && table_def != nullptr) { |
| 7960 |
1/2✓ Branch 0 taken 3263178 times.
✗ Branch 1 not taken.
|
3263178 | ib_table->version = dd_get_version(table_def); |
| 7961 | } | ||
| 7962 | |||
| 7963 |
2/2✓ Branch 0 taken 3462453 times.
✓ Branch 1 taken 28840 times.
|
3491293 | if (ib_table != nullptr) { |
| 7964 |
1/2✓ Branch 0 taken 3462453 times.
✗ Branch 1 not taken.
|
3462453 | dict_table_ddl_release(ib_table); |
| 7965 | } | ||
| 7966 | } | ||
| 7967 | |||
| 7968 |
1/2✓ Branch 0 taken 4374135 times.
✗ Branch 1 not taken.
|
4374135 | dict_sys_mutex_exit(); |
| 7969 | |||
| 7970 |
2/2✓ Branch 0 taken 911680 times.
✓ Branch 1 taken 3462455 times.
|
4374135 | if (!cached) { |
| 7971 |
1/2✓ Branch 0 taken 911680 times.
✗ Branch 1 not taken.
|
911680 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 7972 |
1/2✓ Branch 0 taken 911680 times.
✗ Branch 1 not taken.
|
911680 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 7973 | |||
| 7974 |
1/2✓ Branch 0 taken 911679 times.
✗ Branch 1 not taken.
|
911680 | ib_table = dd_open_table(client, table, norm_name, table_def, thd); |
| 7975 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 911677 times.
|
911679 | if (!ib_table) { |
| 7976 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | set_my_errno(ENOENT); |
| 7977 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 7978 | } | ||
| 7979 |
2/2✓ Branch 0 taken 911677 times.
✓ Branch 1 taken 2 times.
|
911679 | } |
| 7980 | } else { | ||
| 7981 |
1/2✓ Branch 0 taken 182867 times.
✗ Branch 1 not taken.
|
182868 | ib_table->acquire(); |
| 7982 |
2/4✓ Branch 0 taken 182867 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 182867 times.
|
182867 | ut_ad(ib_table->is_intrinsic()); |
| 7983 | } | ||
| 7984 | |||
| 7985 |
2/2✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 2 times.
|
4556999 | if (ib_table != nullptr) { |
| 7986 | /* Make sure table->is_dd_table is set */ | ||
| 7987 | 4556997 | std::string db_str; | |
| 7988 | 4556997 | std::string tbl_str; | |
| 7989 |
2/4✓ Branch 0 taken 4556997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556997 times.
✗ Branch 3 not taken.
|
4556997 | dict_name::get_table(ib_table->name.m_name, db_str, tbl_str); |
| 7990 | |||
| 7991 | 4556997 | ib_table->is_dd_table = | |
| 7992 |
4/8✓ Branch 0 taken 4556997 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556997 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4556997 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4556997 times.
✗ Branch 7 not taken.
|
4556997 | dd::get_dictionary()->is_dd_table_name(db_str.c_str(), tbl_str.c_str()); |
| 7993 | 4556996 | } | |
| 7994 | |||
| 7995 | /* m_share might hold pointers to dict table indexes without any pin. | ||
| 7996 | We must always allocate m_share after opening the dict_table_t object | ||
| 7997 | and free it before de-allocating dict_table_t to avoid race. */ | ||
| 7998 |
2/2✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 2 times.
|
4556999 | if (ib_table != nullptr) { |
| 7999 |
1/2✓ Branch 0 taken 4556997 times.
✗ Branch 1 not taken.
|
4556997 | m_share = get_share(name); |
| 8000 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4556997 times.
|
4556997 | if (m_share == nullptr) { |
| 8001 | ✗ | dict_table_close(ib_table, false, false); | |
| 8002 | ✗ | return HA_ERR_SE_OUT_OF_MEMORY; | |
| 8003 | } | ||
| 8004 | |||
| 8005 |
3/10✗ Branch 0 not taken.
✓ Branch 1 taken 4556997 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4556997 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4556997 times.
|
4556997 | if (UNIV_UNLIKELY(m_share->ib_table && m_share->ib_table->is_corrupt && |
| 8006 | srv_pass_corrupt_table <= 1)) { | ||
| 8007 | ✗ | free_share_and_nullify(&m_share); | |
| 8008 | ✗ | dict_table_close(ib_table, false, false); | |
| 8009 | ✗ | return HA_ERR_CRASHED_ON_USAGE; | |
| 8010 | } | ||
| 8011 | } | ||
| 8012 | |||
| 8013 |
3/4✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556998 times.
|
9113995 | if (ib_table != nullptr && |
| 8014 |
2/2✓ Branch 0 taken 4555697 times.
✓ Branch 1 taken 1300 times.
|
4556997 | ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) && |
| 8015 |
4/6✓ Branch 0 taken 4555697 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4555698 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1300 times.
✓ Branch 5 taken 4555697 times.
|
9112694 | table->s->fields != dict_table_get_n_tot_u_cols(ib_table)) || |
| 8016 | 4556998 | (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID) && | |
| 8017 |
3/4✓ Branch 0 taken 1300 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1299 times.
|
1300 | (table->s->fields != dict_table_get_n_tot_u_cols(ib_table) - 1)))) { |
| 8018 | ✗ | ib::warn(ER_IB_MSG_556) | |
| 8019 | ✗ | << "Table " << norm_name << " contains " << ib_table->get_n_user_cols() | |
| 8020 | << " user" | ||
| 8021 | ✗ | " defined columns in InnoDB, but " | |
| 8022 | ✗ | << table->s->fields | |
| 8023 | << " columns in MySQL. Please check" | ||
| 8024 | " INFORMATION_SCHEMA.INNODB_COLUMNS and " REFMAN | ||
| 8025 | "innodb-troubleshooting.html for how to resolve the" | ||
| 8026 | ✗ | " issue."; | |
| 8027 | |||
| 8028 | /* Mark this table as corrupted, so the drop table | ||
| 8029 | or force recovery can still use it, but not others. */ | ||
| 8030 | ✗ | ib_table->first_index()->type |= DICT_CORRUPT; | |
| 8031 | ✗ | free_share_and_nullify(&m_share); | |
| 8032 | ✗ | dict_table_close(ib_table, false, false); | |
| 8033 | ✗ | ib_table = nullptr; | |
| 8034 | } | ||
| 8035 | |||
| 8036 |
5/10✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556997 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4556998 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4556998 times.
|
4556998 | if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt && |
| 8037 | srv_pass_corrupt_table <= 1)) { | ||
| 8038 | ✗ | free_share_and_nullify(&m_share); | |
| 8039 | ✗ | dict_table_close(ib_table, false, false); | |
| 8040 | ✗ | return HA_ERR_CRASHED_ON_USAGE; | |
| 8041 | } | ||
| 8042 | |||
| 8043 | 9113988 | FilSpace space; | |
| 8044 |
4/6✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4556996 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4556999 times.
✗ Branch 5 not taken.
|
4556998 | if (ib_table) space = fil_space_acquire_silent(ib_table->space); |
| 8045 | |||
| 8046 | /* For encrypted table, check if the encryption info in data | ||
| 8047 | file can't be retrieved properly, mark it as corrupted. */ | ||
| 8048 | 9113995 | if (ib_table != nullptr && | |
| 8049 |
3/4✓ Branch 0 taken 4556996 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4541191 times.
✓ Branch 3 taken 15805 times.
|
4556997 | (dd_is_table_in_encrypted_tablespace(ib_table) || |
| 8050 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 4541191 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4541191 | (ib_table->keyring_encryption_info.page0_has_crypt_data && |
| 8051 | ✗ | ib_table->keyring_encryption_info.is_encryption_in_progress())) && | |
| 8052 |
8/8✓ Branch 0 taken 4556997 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 309 times.
✓ Branch 3 taken 15491 times.
✓ Branch 4 taken 269 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 269 times.
✓ Branch 7 taken 4556730 times.
|
9113996 | ib_table->ibd_file_missing && !dict_table_is_discarded(ib_table)) { |
| 8053 | /* Mark this table as corrupted, so the drop table | ||
| 8054 | or force recovery can still use it, but not others. */ | ||
| 8055 | 269 | FilSpace space; | |
| 8056 | 269 | int error = 0; | |
| 8057 |
3/6✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
|
269 | if (ib_table) space = fil_space_acquire_silent(ib_table->space); |
| 8058 |
2/4✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
|
538 | if (space() == NULL && |
| 8059 |
1/2✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
|
269 | (ib_table->keyring_encryption_info.keyring_encryption_key_is_missing || |
| 8060 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
|
269 | ib_table->keyring_encryption_info.page0_has_crypt_data)) { |
| 8061 | /* Proper error message has been already printed by | ||
| 8062 | * Datafile::validate_first_page, thus we do not print anything here */ | ||
| 8063 | ✗ | error = HA_ERR_ENCRYPTION_KEY_MISSING; | |
| 8064 | } else { | ||
| 8065 |
1/2✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
|
269 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 8066 | 269 | error = HA_ERR_TABLE_CORRUPT; | |
| 8067 | } | ||
| 8068 |
1/2✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
|
269 | dict_table_close(ib_table, false, false); |
| 8069 | 269 | ib_table = nullptr; | |
| 8070 | |||
| 8071 |
1/2✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
|
269 | free_share_and_nullify(&m_share); |
| 8072 | 269 | return error; | |
| 8073 | 269 | } | |
| 8074 | |||
| 8075 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4556728 times.
|
4556730 | if (nullptr == ib_table) { |
| 8076 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | ib::warn(ER_IB_MSG_557) |
| 8077 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | << "Cannot open table " << norm_name << TROUBLESHOOTING_MSG; |
| 8078 | |||
| 8079 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | set_my_errno(ENOENT); |
| 8080 | |||
| 8081 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 8082 | } | ||
| 8083 | |||
| 8084 |
1/2✓ Branch 0 taken 4556728 times.
✗ Branch 1 not taken.
|
4556728 | innobase_copy_frm_flags_from_table_share(ib_table, table->s); |
| 8085 | |||
| 8086 |
1/2✓ Branch 0 taken 4556725 times.
✗ Branch 1 not taken.
|
4556728 | dict_stats_init(ib_table); |
| 8087 | |||
| 8088 | 4556725 | MONITOR_INC(MONITOR_TABLE_OPEN); | |
| 8089 | |||
| 8090 | bool no_tablespace; | ||
| 8091 | |||
| 8092 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 4556641 times.
|
4556726 | if (dict_table_is_discarded(ib_table)) { |
| 8093 | /* If the op is an IMPORT, open the space without this warning. */ | ||
| 8094 |
3/4✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 27 times.
|
85 | if (thd_tablespace_op(thd) != Alter_info::ALTER_IMPORT_TABLESPACE) { |
| 8095 | 58 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_DISCARDED, | |
| 8096 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | table->s->table_name.str); |
| 8097 | } | ||
| 8098 | |||
| 8099 | /* Allow an open because a proper DISCARD should have set | ||
| 8100 | all the flags and index root page numbers to FIL_NULL that | ||
| 8101 | should prevent any DML from running but it should allow DDL | ||
| 8102 | operations. */ | ||
| 8103 | 85 | no_tablespace = false; | |
| 8104 | |||
| 8105 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4556593 times.
|
4556641 | } else if (ib_table->ibd_file_missing) { |
| 8106 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_MISSING, norm_name); |
| 8107 | |||
| 8108 | /* This means we have no idea what happened to the tablespace | ||
| 8109 | file, best to play it safe. */ | ||
| 8110 | |||
| 8111 | 48 | no_tablespace = true; | |
| 8112 | } else { | ||
| 8113 | 4556593 | no_tablespace = false; | |
| 8114 | } | ||
| 8115 | |||
| 8116 |
7/8✓ Branch 0 taken 4556726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4556528 times.
✓ Branch 3 taken 198 times.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 4556481 times.
✓ Branch 6 taken 47 times.
✓ Branch 7 taken 4556679 times.
|
4556726 | if (!thd_tablespace_op(thd) && no_tablespace) { |
| 8117 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | free_share_and_nullify(&m_share); |
| 8118 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | set_my_errno(ENOENT); |
| 8119 | |||
| 8120 |
1/2✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
|
47 | dict_table_close(ib_table, false, false); |
| 8121 | |||
| 8122 | 47 | return HA_ERR_TABLESPACE_MISSING; | |
| 8123 | } | ||
| 8124 | |||
| 8125 |
1/2✓ Branch 0 taken 4556677 times.
✗ Branch 1 not taken.
|
4556679 | m_prebuilt = row_create_prebuilt(ib_table, table->s->reclength); |
| 8126 | |||
| 8127 | 4556677 | m_prebuilt->default_rec = table->s->default_values; | |
| 8128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4556677 times.
|
4556677 | ut_ad(m_prebuilt->default_rec); |
| 8129 | |||
| 8130 | 4556677 | m_prebuilt->m_mysql_table = table; | |
| 8131 | 4556677 | m_prebuilt->m_mysql_handler = this; | |
| 8132 | |||
| 8133 |
3/4✓ Branch 0 taken 4556677 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182867 times.
✓ Branch 3 taken 4373810 times.
|
4556677 | if (ib_table->is_intrinsic()) { |
| 8134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 182867 times.
|
182867 | ut_ad(open_flags & HA_OPEN_INTERNAL_TABLE); |
| 8135 | |||
| 8136 |
1/2✓ Branch 0 taken 182867 times.
✗ Branch 1 not taken.
|
182867 | m_prebuilt->m_temp_read_shared = table_share->ref_count() >= 2; |
| 8137 | |||
| 8138 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 182531 times.
|
182867 | if (m_prebuilt->m_temp_read_shared) { |
| 8139 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 224 times.
|
336 | if (ib_table->temp_prebuilt == nullptr) { |
| 8140 | 112 | ib_table->temp_prebuilt = | |
| 8141 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | ut::new_withkey<temp_prebuilt_vec>(UT_NEW_THIS_FILE_PSI_KEY); |
| 8142 | } | ||
| 8143 | |||
| 8144 |
1/2✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
|
336 | ib_table->temp_prebuilt->push_back(m_prebuilt); |
| 8145 | } | ||
| 8146 | 182867 | m_prebuilt->m_temp_tree_modified = false; | |
| 8147 | } | ||
| 8148 | |||
| 8149 | 4556677 | key_used_on_scan = table_share->primary_key; | |
| 8150 | |||
| 8151 |
2/2✓ Branch 0 taken 53155 times.
✓ Branch 1 taken 4503522 times.
|
4556677 | if (ib_table->n_v_cols) { |
| 8152 |
1/2✓ Branch 0 taken 53155 times.
✗ Branch 1 not taken.
|
53155 | dict_sys_mutex_enter(); |
| 8153 |
2/2✓ Branch 0 taken 27960 times.
✓ Branch 1 taken 25195 times.
|
53155 | if (ib_table->vc_templ == nullptr) { |
| 8154 | 27960 | ib_table->vc_templ = | |
| 8155 |
1/2✓ Branch 0 taken 27960 times.
✗ Branch 1 not taken.
|
27960 | ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY); |
| 8156 | 27960 | ib_table->vc_templ->vtempl = nullptr; | |
| 8157 |
2/2✓ Branch 0 taken 24092 times.
✓ Branch 1 taken 1103 times.
|
25195 | } else if (ib_table->get_ref_count() == 1) { |
| 8158 | /* Clean and refresh the template if no one else | ||
| 8159 | get hold on it */ | ||
| 8160 |
1/2✓ Branch 0 taken 24092 times.
✗ Branch 1 not taken.
|
24092 | dict_free_vc_templ(ib_table->vc_templ); |
| 8161 | 24092 | ib_table->vc_templ->vtempl = nullptr; | |
| 8162 | } | ||
| 8163 | |||
| 8164 |
2/2✓ Branch 0 taken 52052 times.
✓ Branch 1 taken 1103 times.
|
53155 | if (ib_table->vc_templ->vtempl == nullptr) { |
| 8165 | 52052 | innobase_build_v_templ(table, ib_table, ib_table->vc_templ, nullptr, true, | |
| 8166 |
1/2✓ Branch 0 taken 52052 times.
✗ Branch 1 not taken.
|
52052 | m_share->table_name); |
| 8167 | } | ||
| 8168 | |||
| 8169 |
1/2✓ Branch 0 taken 53155 times.
✗ Branch 1 not taken.
|
53155 | dict_sys_mutex_exit(); |
| 8170 | } | ||
| 8171 | |||
| 8172 |
2/4✓ Branch 0 taken 4556678 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556678 times.
|
4556677 | if (!innobase_build_index_translation(table, ib_table, m_share)) { |
| 8173 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_CANT_BUILD_INDEX_XLATION_TABLE_FOR, name); | |
| 8174 | } | ||
| 8175 | |||
| 8176 | /* Allocate a buffer for a 'row reference'. A row reference is | ||
| 8177 | a string of bytes of length ref_length which uniquely specifies | ||
| 8178 | a row in our table. Note that MySQL may also compare two row | ||
| 8179 | references for equality by doing a simple memcmp on the strings | ||
| 8180 | of length ref_length! */ | ||
| 8181 | |||
| 8182 |
3/4✓ Branch 0 taken 4556679 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3867636 times.
✓ Branch 3 taken 689043 times.
|
4556678 | if (!row_table_got_default_clust_index(ib_table)) { |
| 8183 | 3867636 | m_prebuilt->clust_index_was_generated = false; | |
| 8184 | |||
| 8185 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3867636 times.
|
3867636 | if (table_share->is_missing_primary_key()) { |
| 8186 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_PK_NOT_IN_MYSQL, name); | |
| 8187 | |||
| 8188 | /* This mismatch could cause further problems | ||
| 8189 | if not attended, bring this to the user's attention | ||
| 8190 | by printing a warning in addition to log a message | ||
| 8191 | in the errorlog */ | ||
| 8192 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX, | |
| 8193 | "InnoDB: Table %s has a" | ||
| 8194 | " primary key in InnoDB data" | ||
| 8195 | " dictionary, but not in" | ||
| 8196 | " MySQL!", | ||
| 8197 | name); | ||
| 8198 | |||
| 8199 | /* If table_share->is_missing_primary_key(), | ||
| 8200 | the table_share->primary_key | ||
| 8201 | value could be out of bound if continue to index | ||
| 8202 | into key_info[] array. Find InnoDB primary index, | ||
| 8203 | and assign its key_length to ref_length. | ||
| 8204 | In addition, since MySQL indexes are sorted starting | ||
| 8205 | with primary index, unique index etc., initialize | ||
| 8206 | ref_length to the first index key length in | ||
| 8207 | case we fail to find InnoDB cluster index. | ||
| 8208 | |||
| 8209 | Please note, this will not resolve the primary | ||
| 8210 | index mismatch problem, other side effects are | ||
| 8211 | possible if users continue to use the table. | ||
| 8212 | However, we allow this table to be opened so | ||
| 8213 | that user can adopt necessary measures for the | ||
| 8214 | mismatch while still being accessible to the table | ||
| 8215 | date. */ | ||
| 8216 | ✗ | if (!table->key_info) { | |
| 8217 | ✗ | ut_ad(!table->s->keys); | |
| 8218 | ✗ | ref_length = 0; | |
| 8219 | } else { | ||
| 8220 | ✗ | ref_length = table->key_info[0].key_length; | |
| 8221 | } | ||
| 8222 | |||
| 8223 | /* Find corresponding cluster index | ||
| 8224 | key length in MySQL's key_info[] array */ | ||
| 8225 | ✗ | for (uint i = 0; i < table->s->keys; i++) { | |
| 8226 | dict_index_t *index; | ||
| 8227 | ✗ | index = innobase_get_index(i); | |
| 8228 | ✗ | if (index->is_clustered()) { | |
| 8229 | ✗ | ref_length = table->key_info[i].key_length; | |
| 8230 | } | ||
| 8231 | } | ||
| 8232 | } else { | ||
| 8233 | /* MySQL allocates the buffer for ref. | ||
| 8234 | key_info->key_length includes space for all key | ||
| 8235 | columns + one byte for each column that may be | ||
| 8236 | NULL. ref_length must be as exact as possible to | ||
| 8237 | save space, because all row reference buffers are | ||
| 8238 | allocated based on ref_length. */ | ||
| 8239 | |||
| 8240 | 3867636 | ref_length = table->key_info[table_share->primary_key].key_length; | |
| 8241 | } | ||
| 8242 | } else { | ||
| 8243 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 689043 times.
|
689043 | if (!table_share->is_missing_primary_key()) { |
| 8244 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_PK_ONLY_IN_MYSQL, name); | |
| 8245 | |||
| 8246 | /* This mismatch could cause further problems | ||
| 8247 | if not attended, bring this to the user attention | ||
| 8248 | by printing a warning in addition to log a message | ||
| 8249 | in the errorlog */ | ||
| 8250 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_SUCH_INDEX, | |
| 8251 | "InnoDB: Table %s has no" | ||
| 8252 | " primary key in InnoDB data" | ||
| 8253 | " dictionary, but has one in" | ||
| 8254 | " MySQL!", | ||
| 8255 | name); | ||
| 8256 | } | ||
| 8257 | |||
| 8258 | 689043 | m_prebuilt->clust_index_was_generated = true; | |
| 8259 | |||
| 8260 | 689043 | ref_length = DATA_ROW_ID_LEN; | |
| 8261 | |||
| 8262 | /* If we automatically created the clustered index, then | ||
| 8263 | MySQL does not know about it, and MySQL must NOT be aware | ||
| 8264 | of the index used on scan, to make it avoid checking if we | ||
| 8265 | update the column of the index. That is why we assert below | ||
| 8266 | that key_used_on_scan is the undefined value MAX_KEY. | ||
| 8267 | The column is the row id in the automatical generation case, | ||
| 8268 | and it will never be updated anyway. */ | ||
| 8269 | |||
| 8270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 689043 times.
|
689043 | if (key_used_on_scan != MAX_KEY) { |
| 8271 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_CLUSTERED_INDEX_PRIVATE, name, | |
| 8272 | (ulong)key_used_on_scan); | ||
| 8273 | } | ||
| 8274 | } | ||
| 8275 | |||
| 8276 | /* Index block size in InnoDB: used by MySQL in query optimization */ | ||
| 8277 | 4556679 | stats.block_size = UNIV_PAGE_SIZE; | |
| 8278 | |||
| 8279 | /* Only if the table has an AUTOINC column. */ | ||
| 8280 |
4/4✓ Branch 0 taken 4556678 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4556592 times.
✓ Branch 3 taken 86 times.
|
4556679 | if (m_prebuilt->table != nullptr && !m_prebuilt->table->ibd_file_missing && |
| 8281 |
2/2✓ Branch 0 taken 1718668 times.
✓ Branch 1 taken 2837924 times.
|
4556592 | table->found_next_number_field != NULL) { |
| 8282 | 1718668 | dict_table_t *ib_table = m_prebuilt->table; | |
| 8283 | |||
| 8284 |
1/2✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
|
1718668 | dict_table_autoinc_lock(ib_table); |
| 8285 | |||
| 8286 |
1/2✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
|
1718668 | uint64_t autoinc = dict_table_autoinc_read(ib_table); |
| 8287 | 1718668 | uint64_t autoinc_persisted = 0; | |
| 8288 | |||
| 8289 |
1/2✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
|
1718668 | mutex_enter(ib_table->autoinc_persisted_mutex); |
| 8290 | 1718668 | autoinc_persisted = ib_table->autoinc_persisted; | |
| 8291 |
1/2✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
|
1718668 | mutex_exit(ib_table->autoinc_persisted_mutex); |
| 8292 | |||
| 8293 | /* Since a table can already be "open" in InnoDB's internal | ||
| 8294 | data dictionary, we only init the autoinc counter once, the | ||
| 8295 | first time the table is loaded. We can safely reuse the | ||
| 8296 | autoinc value from a previous MySQL open. */ | ||
| 8297 |
4/4✓ Branch 0 taken 1692901 times.
✓ Branch 1 taken 25767 times.
✓ Branch 2 taken 100863 times.
✓ Branch 3 taken 1592038 times.
|
1718668 | if (autoinc == 0 || autoinc == autoinc_persisted) { |
| 8298 | /* If autoinc is 0, it means the counter was never | ||
| 8299 | used or imported from a tablespace without .cfg file. | ||
| 8300 | We have to search the index to get proper counter. | ||
| 8301 | If only the second condition is true, it means it's | ||
| 8302 | the first time open for the table, we just want to | ||
| 8303 | calculate the next counter */ | ||
| 8304 |
1/2✓ Branch 0 taken 126630 times.
✗ Branch 1 not taken.
|
126630 | innobase_initialize_autoinc(); |
| 8305 | } | ||
| 8306 | |||
| 8307 |
1/2✓ Branch 0 taken 1718668 times.
✗ Branch 1 not taken.
|
1718668 | dict_table_autoinc_set_col_pos( |
| 8308 | 1718668 | ib_table, table->found_next_number_field->field_index()); | |
| 8309 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1718668 times.
|
1718668 | ut_ad(dict_table_has_autoinc_col(ib_table)); |
| 8310 | |||
| 8311 |
1/2✓ Branch 0 taken 1718667 times.
✗ Branch 1 not taken.
|
1718668 | dict_table_autoinc_unlock(ib_table); |
| 8312 | } | ||
| 8313 | |||
| 8314 | /* Set plugin parser for fulltext index */ | ||
| 8315 |
2/2✓ Branch 0 taken 11595537 times.
✓ Branch 1 taken 4556679 times.
|
16152216 | for (uint i = 0; i < table->s->keys; i++) { |
| 8316 |
2/2✓ Branch 0 taken 1255 times.
✓ Branch 1 taken 11594282 times.
|
11595537 | if (table->key_info[i].flags & HA_USES_PARSER) { |
| 8317 |
1/2✓ Branch 0 taken 1255 times.
✗ Branch 1 not taken.
|
1255 | dict_index_t *index = innobase_get_index(i); |
| 8318 | 1255 | plugin_ref parser = table->key_info[i].parser; | |
| 8319 | |||
| 8320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1255 times.
|
1255 | ut_ad(index->type & DICT_FTS); |
| 8321 | 1255 | index->parser = | |
| 8322 | 1255 | static_cast<st_mysql_ftparser *>(plugin_decl(parser)->info); | |
| 8323 | |||
| 8324 | 1255 | index->is_ngram = strncmp(plugin_name(parser)->str, FTS_NGRAM_PARSER_NAME, | |
| 8325 | 1255 | plugin_name(parser)->length) == 0; | |
| 8326 | |||
| 8327 |
3/4✓ Branch 0 taken 1256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1252 times.
|
1255 | DBUG_EXECUTE_IF("fts_instrument_use_default_parser", |
| 8328 | index->parser = &fts_default_parser;); | ||
| 8329 | } | ||
| 8330 | } | ||
| 8331 | |||
| 8332 |
1/2✓ Branch 0 taken 4556677 times.
✗ Branch 1 not taken.
|
4556679 | info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); |
| 8333 | |||
| 8334 | dberr_t err = | ||
| 8335 |
1/2✓ Branch 0 taken 4556675 times.
✗ Branch 1 not taken.
|
4556677 | dict_set_compression(m_prebuilt->table, table->s->compress.str, false); |
| 8336 | |||
| 8337 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4116304 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 440370 times.
|
4556675 | switch (err) { |
| 8338 | 1 | case DB_NOT_FOUND: | |
| 8339 | case DB_UNSUPPORTED: | ||
| 8340 | /* We will do another check before the create | ||
| 8341 | table and push the error to the client there. */ | ||
| 8342 | 1 | break; | |
| 8343 | |||
| 8344 | 4116304 | case DB_IO_NO_PUNCH_HOLE_TABLESPACE: | |
| 8345 | /* We did the check in the 'if' above. */ | ||
| 8346 | |||
| 8347 | case DB_IO_NO_PUNCH_HOLE_FS: | ||
| 8348 | /* During open we can't check whether the FS supports | ||
| 8349 | punch hole or not, at least on Linux. */ | ||
| 8350 | 4116304 | break; | |
| 8351 | |||
| 8352 | ✗ | default: | |
| 8353 | ✗ | ut_error; | |
| 8354 | |||
| 8355 | 440370 | case DB_SUCCESS: | |
| 8356 | 440370 | break; | |
| 8357 | } | ||
| 8358 | |||
| 8359 | #ifdef UNIV_DEBUG | ||
| 8360 | fts_aux_table_t aux_table; | ||
| 8361 | |||
| 8362 |
2/4✓ Branch 0 taken 4556671 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556671 times.
|
4556675 | if (fts_is_aux_table_name(&aux_table, norm_name, strlen(norm_name))) { |
| 8363 | ✗ | ut_ad(m_prebuilt->table->is_fts_aux()); | |
| 8364 | } | ||
| 8365 | #endif /* UNIV_DEBUG */ | ||
| 8366 | |||
| 8367 |
2/4✓ Branch 0 taken 4556675 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4556675 times.
|
4556671 | if (m_prebuilt->table->is_fts_aux()) { |
| 8368 | ✗ | dict_table_close(m_prebuilt->table, false, false); | |
| 8369 | } | ||
| 8370 | |||
| 8371 | 4556672 | return 0; | |
| 8372 | 4556998 | } | |
| 8373 | |||
| 8374 | 319350 | handler *ha_innobase::clone(const char *name, /*!< in: table name */ | |
| 8375 | MEM_ROOT *mem_root) /*!< in: memory context */ | ||
| 8376 | { | ||
| 8377 |
1/2✓ Branch 0 taken 319350 times.
✗ Branch 1 not taken.
|
319350 | DBUG_TRACE; |
| 8378 | |||
| 8379 | ha_innobase *new_handler = | ||
| 8380 |
3/4✓ Branch 0 taken 319350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 319349 times.
✓ Branch 3 taken 1 times.
|
319350 | dynamic_cast<ha_innobase *>(handler::clone(name, mem_root)); |
| 8381 | |||
| 8382 |
2/2✓ Branch 0 taken 319349 times.
✓ Branch 1 taken 1 times.
|
319350 | if (new_handler != nullptr) { |
| 8383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 319349 times.
|
319349 | assert(new_handler->m_prebuilt != nullptr); |
| 8384 | |||
| 8385 | 319349 | new_handler->m_prebuilt->select_lock_type = m_prebuilt->select_lock_type; | |
| 8386 | } | ||
| 8387 | |||
| 8388 | 319350 | return new_handler; | |
| 8389 | 319350 | } | |
| 8390 | |||
| 8391 | 2175539 | uint ha_innobase::max_supported_key_part_length( | |
| 8392 | HA_CREATE_INFO *create_info) const { | ||
| 8393 | /* A table format specific index column length check will be performed | ||
| 8394 | at ha_innobase::add_index() and row_create_index_for_mysql() */ | ||
| 8395 |
2/2✓ Branch 0 taken 5973 times.
✓ Branch 1 taken 2169566 times.
|
2175539 | switch (create_info->row_type) { |
| 8396 | 5973 | case ROW_TYPE_REDUNDANT: | |
| 8397 | case ROW_TYPE_COMPACT: | ||
| 8398 | 5973 | return (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1); | |
| 8399 | break; | ||
| 8400 | 2169566 | default: | |
| 8401 | 2169566 | return (REC_VERSION_56_MAX_INDEX_COL_LEN); | |
| 8402 | } | ||
| 8403 | } | ||
| 8404 | |||
| 8405 | /** Closes a handle to an InnoDB table. | ||
| 8406 | @return 0 */ | ||
| 8407 | |||
| 8408 | 4433751 | int ha_innobase::close() { | |
| 8409 |
1/2✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
|
4433751 | DBUG_TRACE; |
| 8410 | |||
| 8411 |
2/2✓ Branch 0 taken 336 times.
✓ Branch 1 taken 4433416 times.
|
4433752 | if (m_prebuilt->m_temp_read_shared) { |
| 8412 | 336 | temp_prebuilt_vec *vec = m_prebuilt->table->temp_prebuilt; | |
| 8413 |
2/4✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
|
336 | ut_ad(m_prebuilt->table->is_intrinsic()); |
| 8414 |
2/4✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 336 times.
✗ Branch 3 not taken.
|
336 | vec->erase(std::remove(vec->begin(), vec->end(), m_prebuilt), vec->end()); |
| 8415 | } | ||
| 8416 | |||
| 8417 |
1/2✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
|
4433752 | free_share_and_nullify(&m_share); |
| 8418 | |||
| 8419 |
1/2✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
|
4433752 | row_prebuilt_free(m_prebuilt, false); |
| 8420 | |||
| 8421 |
2/2✓ Branch 0 taken 228162 times.
✓ Branch 1 taken 4205590 times.
|
4433752 | if (m_upd_buf != nullptr) { |
| 8422 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 228162 times.
|
228162 | ut_ad(m_upd_buf_size != 0); |
| 8423 |
1/2✓ Branch 0 taken 228162 times.
✗ Branch 1 not taken.
|
228162 | my_free(m_upd_buf); |
| 8424 | 228162 | m_upd_buf = nullptr; | |
| 8425 | 228162 | m_upd_buf_size = 0; | |
| 8426 | } | ||
| 8427 | |||
| 8428 | 4433752 | MONITOR_INC(MONITOR_TABLE_CLOSE); | |
| 8429 | |||
| 8430 | /* Tell InnoDB server that there might be work for | ||
| 8431 | utility threads: */ | ||
| 8432 | |||
| 8433 |
1/2✓ Branch 0 taken 4433752 times.
✗ Branch 1 not taken.
|
4433752 | srv_active_wake_master_thread(); |
| 8434 | |||
| 8435 | 4433752 | return 0; | |
| 8436 | 4433752 | } | |
| 8437 | |||
| 8438 | /* The following accessor functions should really be inside MySQL code! */ | ||
| 8439 | |||
| 8440 | /** Gets field offset for a field in a table. | ||
| 8441 | @param[in] table MySQL table object | ||
| 8442 | @param[in] field MySQL field object | ||
| 8443 | @return offset */ | ||
| 8444 | 2289559526 | static inline uint get_field_offset(const TABLE *table, const Field *field) { | |
| 8445 | 2289559526 | return field->offset(table->record[0]); | |
| 8446 | } | ||
| 8447 | |||
| 8448 | /** Compare two character string according to their charset. | ||
| 8449 | @param[in] cs Character set | ||
| 8450 | @param[in] p1 Key | ||
| 8451 | @param[in] p2 Node */ | ||
| 8452 | 279105551 | extern int innobase_fts_text_cmp(const void *cs, const void *p1, | |
| 8453 | const void *p2) { | ||
| 8454 | 279105551 | const CHARSET_INFO *charset = (const CHARSET_INFO *)cs; | |
| 8455 | 279105551 | const fts_string_t *s1 = (const fts_string_t *)p1; | |
| 8456 | 279105551 | const fts_string_t *s2 = (const fts_string_t *)p2; | |
| 8457 | |||
| 8458 | 558221584 | return (ha_compare_text(charset, s1->f_str, static_cast<uint>(s1->f_len), | |
| 8459 | 279105551 | s2->f_str, static_cast<uint>(s2->f_len), false)); | |
| 8460 | } | ||
| 8461 | |||
| 8462 | /** Compare two FTS character strings case insensitively according to their | ||
| 8463 | charset. This assumes that s1 is already in lower case. | ||
| 8464 | @param[in] cs character set | ||
| 8465 | @param[in] s1 key | ||
| 8466 | @param[in] s2 node | ||
| 8467 | @return 0 if the two strings are equal */ | ||
| 8468 | 1132 | int innobase_fts_nocase_compare(const CHARSET_INFO *cs, const fts_string_t *s1, | |
| 8469 | const fts_string_t *s2) { | ||
| 8470 | ulint newlen; | ||
| 8471 | |||
| 8472 |
2/2✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 103 times.
|
1132 | if (!my_binary_compare(cs)) { |
| 8473 | 1029 | my_casedn_str(cs, (char *)s2->f_str); | |
| 8474 | } | ||
| 8475 | |||
| 8476 | 1132 | newlen = strlen((const char *)s2->f_str); | |
| 8477 | |||
| 8478 | 2264 | return (ha_compare_text(cs, s1->f_str, static_cast<uint>(s1->f_len), | |
| 8479 | 1132 | s2->f_str, static_cast<uint>(newlen), false)); | |
| 8480 | } | ||
| 8481 | |||
| 8482 | #endif /* UNIV_HOTBACKUP */ | ||
| 8483 | |||
| 8484 | /** Compare two character strings case insensitively according to their | ||
| 8485 | charset. | ||
| 8486 | @param[in] cs character set | ||
| 8487 | @param[in] s1 string 1 | ||
| 8488 | @param[in] s2 string 2 | ||
| 8489 | @return 0 if the two strings are equal */ | ||
| 8490 | ✗ | int innobase_nocase_compare(const void *cs, const char *s1, const char *s2) { | |
| 8491 | ✗ | const CHARSET_INFO *charset = static_cast<const CHARSET_INFO *>(cs); | |
| 8492 | ✗ | const uchar *str1 = reinterpret_cast<const uchar *>(s1); | |
| 8493 | ✗ | const uchar *str2 = reinterpret_cast<const uchar *>(s2); | |
| 8494 | ✗ | uint len1 = static_cast<uint>(strlen(s1)); | |
| 8495 | ✗ | uint len2 = static_cast<uint>(strlen(s2)); | |
| 8496 | |||
| 8497 | /* This function returns zero if the two strings are equal. */ | ||
| 8498 | ✗ | return (ha_compare_text(charset, str1, len1, str2, len2, false)); | |
| 8499 | } | ||
| 8500 | |||
| 8501 | #ifndef UNIV_HOTBACKUP | ||
| 8502 | |||
| 8503 | 4386331 | ulint innobase_strnxfrm(const CHARSET_INFO *cs, const uchar *str, | |
| 8504 | const ulint len) { | ||
| 8505 | uchar mystr[2]; | ||
| 8506 | ulint value; | ||
| 8507 | |||
| 8508 |
2/4✓ Branch 0 taken 4386487 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4386490 times.
|
4386331 | if (!str || len == 0) { |
| 8509 | ✗ | return (0); | |
| 8510 | } | ||
| 8511 | |||
| 8512 |
1/2✓ Branch 0 taken 4386073 times.
✗ Branch 1 not taken.
|
4386490 | my_strnxfrm(cs, (uchar *)mystr, 2, str, len); |
| 8513 | |||
| 8514 | 4386073 | value = mach_read_from_2(mystr); | |
| 8515 | |||
| 8516 |
2/2✓ Branch 0 taken 4374355 times.
✓ Branch 1 taken 11442 times.
|
4385797 | if (value > 255) { |
| 8517 | 4374355 | value = value / 256; | |
| 8518 | } | ||
| 8519 | |||
| 8520 | 4385797 | return (value); | |
| 8521 | } | ||
| 8522 | |||
| 8523 | /** Compare two character string according to their charset. | ||
| 8524 | @param[in] cs Character set | ||
| 8525 | @param[in] p1 Key | ||
| 8526 | @param[in] p2 Node */ | ||
| 8527 | 549 | extern int innobase_fts_text_cmp_prefix(const void *cs, const void *p1, | |
| 8528 | const void *p2) { | ||
| 8529 | 549 | const CHARSET_INFO *charset = (const CHARSET_INFO *)cs; | |
| 8530 | 549 | const fts_string_t *s1 = (const fts_string_t *)p1; | |
| 8531 | 549 | const fts_string_t *s2 = (const fts_string_t *)p2; | |
| 8532 | int result; | ||
| 8533 | |||
| 8534 | 1098 | result = ha_compare_text(charset, s2->f_str, static_cast<uint>(s2->f_len), | |
| 8535 | 549 | s1->f_str, static_cast<uint>(s1->f_len), true); | |
| 8536 | |||
| 8537 | /* We switched s1, s2 position in ha_compare_text. So we need | ||
| 8538 | to negate the result */ | ||
| 8539 | 549 | return (-result); | |
| 8540 | } | ||
| 8541 | |||
| 8542 | /** Makes all characters in a string lower case. | ||
| 8543 | @param[in] cs Character set | ||
| 8544 | @param[in] src String to put in lower case | ||
| 8545 | @param[in] src_len Input string length | ||
| 8546 | @param[in] dst Buffer for result string | ||
| 8547 | @param[in] dst_len Buffer size */ | ||
| 8548 | 16547990 | extern size_t innobase_fts_casedn_str(CHARSET_INFO *cs, char *src, | |
| 8549 | size_t src_len, char *dst, | ||
| 8550 | size_t dst_len) { | ||
| 8551 |
2/2✓ Branch 0 taken 16546669 times.
✓ Branch 1 taken 1321 times.
|
16547990 | if (cs->casedn_multiply == 1) { |
| 8552 | 16546669 | memcpy(dst, src, src_len); | |
| 8553 | 16546669 | dst[src_len] = 0; | |
| 8554 | 16546669 | my_casedn_str(cs, dst); | |
| 8555 | |||
| 8556 | 16547155 | return (strlen(dst)); | |
| 8557 | } else { | ||
| 8558 | 1364 | return (cs->cset->casedn(cs, src, src_len, dst, dst_len)); | |
| 8559 | } | ||
| 8560 | } | ||
| 8561 | |||
| 8562 | /** Get the next token from the given string and store it in *token. | ||
| 8563 | It is mostly copied from MyISAM's doc parsing function ft_simple_get_word() | ||
| 8564 | @return length of string processed */ | ||
| 8565 | 16892267 | ulint innobase_mysql_fts_get_token( | |
| 8566 | CHARSET_INFO *cs, /*!< in: Character set */ | ||
| 8567 | const byte *start, /*!< in: start of text */ | ||
| 8568 | const byte *end, /*!< in: one character past end of | ||
| 8569 | text */ | ||
| 8570 | bool extra_word_chars, /*!< in: whether consider all non-whitespace | ||
| 8571 | characters to be word characters */ | ||
| 8572 | fts_string_t *token) /*!< out: token's text */ | ||
| 8573 | { | ||
| 8574 | int mbl; | ||
| 8575 | 16892267 | const uchar *doc = start; | |
| 8576 | |||
| 8577 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16891654 times.
|
16892267 | ut_a(cs); |
| 8578 | |||
| 8579 | 16891654 | token->f_n_char = token->f_len = 0; | |
| 8580 | 16891654 | token->f_str = nullptr; | |
| 8581 | |||
| 8582 | for (;;) { | ||
| 8583 |
2/2✓ Branch 0 taken 10270 times.
✓ Branch 1 taken 37231573 times.
|
37241843 | if (doc >= end) { |
| 8584 | 10270 | return (doc - start); | |
| 8585 | } | ||
| 8586 | |||
| 8587 | int ctype; | ||
| 8588 | |||
| 8589 |
1/2✓ Branch 0 taken 37240105 times.
✗ Branch 1 not taken.
|
37231573 | mbl = cs->cset->ctype(cs, &ctype, doc, (const uchar *)end); |
| 8590 | |||
| 8591 |
2/2✓ Branch 0 taken 16891008 times.
✓ Branch 1 taken 20350189 times.
|
37240105 | if (true_word_char(ctype, extra_word_chars, *doc)) { |
| 8592 | 16891008 | break; | |
| 8593 | } | ||
| 8594 | |||
| 8595 |
2/4✓ Branch 0 taken 20360577 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
20350189 | doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1); |
| 8596 | 20350189 | } | |
| 8597 | |||
| 8598 | 16891008 | ulint length = 0; | |
| 8599 | |||
| 8600 | 16891008 | token->f_str = const_cast<byte *>(doc); | |
| 8601 | |||
| 8602 |
2/2✓ Branch 0 taken 164453290 times.
✓ Branch 1 taken 1722335 times.
|
166175625 | while (doc < end) { |
| 8603 | int ctype; | ||
| 8604 | |||
| 8605 |
1/2✓ Branch 0 taken 164461796 times.
✗ Branch 1 not taken.
|
164453290 | mbl = cs->cset->ctype(cs, &ctype, (uchar *)doc, (uchar *)end); |
| 8606 |
2/2✓ Branch 0 taken 15175709 times.
✓ Branch 1 taken 149284617 times.
|
164461796 | if (!true_word_char(ctype, extra_word_chars, *doc)) { |
| 8607 | 15175709 | break; | |
| 8608 | } | ||
| 8609 | |||
| 8610 | 149284617 | ++length; | |
| 8611 | |||
| 8612 |
1/4✓ Branch 0 taken 149300219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
149284617 | doc += mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1); |
| 8613 | } | ||
| 8614 | |||
| 8615 | 16898044 | token->f_len = (uint)(doc - token->f_str); | |
| 8616 | 16898044 | token->f_n_char = length; | |
| 8617 | |||
| 8618 | 16898044 | return (doc - start); | |
| 8619 | } | ||
| 8620 | |||
| 8621 | /** Converts a MySQL type to an InnoDB type. Note that this function returns | ||
| 8622 | the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1 | ||
| 8623 | VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. | ||
| 8624 | @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'; at least | ||
| 8625 | ENUM and SET, and unsigned integer types are 'unsigned types' | ||
| 8626 | @param[in] f MySQL Field | ||
| 8627 | @return DATA_BINARY, DATA_VARCHAR, ... */ | ||
| 8628 | 23667486 | ulint get_innobase_type_from_mysql_type(ulint *unsigned_flag, const void *f) { | |
| 8629 | 23667486 | const class Field *field = reinterpret_cast<const class Field *>(f); | |
| 8630 | |||
| 8631 | /* The following asserts try to check that the MySQL type code fits in | ||
| 8632 | 8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to | ||
| 8633 | the type */ | ||
| 8634 | |||
| 8635 | assert((ulint)MYSQL_TYPE_STRING < 256); | ||
| 8636 | assert((ulint)MYSQL_TYPE_VAR_STRING < 256); | ||
| 8637 | assert((ulint)MYSQL_TYPE_DOUBLE < 256); | ||
| 8638 | assert((ulint)MYSQL_TYPE_FLOAT < 256); | ||
| 8639 | assert((ulint)MYSQL_TYPE_DECIMAL < 256); | ||
| 8640 | |||
| 8641 |
2/2✓ Branch 0 taken 8445352 times.
✓ Branch 1 taken 15222133 times.
|
23667486 | if (field->is_flag_set(UNSIGNED_FLAG)) { |
| 8642 | 8445352 | *unsigned_flag = DATA_UNSIGNED; | |
| 8643 | } else { | ||
| 8644 | 15222133 | *unsigned_flag = 0; | |
| 8645 | } | ||
| 8646 | |||
| 8647 |
4/4✓ Branch 0 taken 21870167 times.
✓ Branch 1 taken 1797320 times.
✓ Branch 2 taken 1901222 times.
✓ Branch 3 taken 21766265 times.
|
45537652 | if (field->real_type() == MYSQL_TYPE_ENUM || |
| 8648 |
2/2✓ Branch 0 taken 103902 times.
✓ Branch 1 taken 21766265 times.
|
21870167 | field->real_type() == MYSQL_TYPE_SET) { |
| 8649 | /* MySQL has field->type() a string type for these, but the | ||
| 8650 | data is actually internally stored as an unsigned integer | ||
| 8651 | code! */ | ||
| 8652 | |||
| 8653 | 1901222 | *unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned | |
| 8654 | flag set to zero, even though | ||
| 8655 | internally this is an unsigned | ||
| 8656 | integer type */ | ||
| 8657 | 1901222 | return (DATA_INT); | |
| 8658 | } | ||
| 8659 | |||
| 8660 |
9/12✓ Branch 0 taken 6454878 times.
✓ Branch 1 taken 1905760 times.
✓ Branch 2 taken 19926 times.
✓ Branch 3 taken 10639066 times.
✓ Branch 4 taken 593263 times.
✓ Branch 5 taken 72421 times.
✓ Branch 6 taken 33219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6253 times.
✓ Branch 9 taken 2041479 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
21766265 | switch (field->type()) { |
| 8661 | /* NOTE that we only allow string types in DATA_MYSQL and | ||
| 8662 | DATA_VARMYSQL */ | ||
| 8663 | 6454878 | case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */ | |
| 8664 | case MYSQL_TYPE_VARCHAR: /* new >= 5.0.3 true VARCHAR */ | ||
| 8665 |
2/2✓ Branch 0 taken 46392 times.
✓ Branch 1 taken 6408486 times.
|
6454878 | if (field->binary()) { |
| 8666 | 46392 | return (DATA_BINARY); | |
| 8667 |
2/2✓ Branch 0 taken 67689 times.
✓ Branch 1 taken 6340797 times.
|
6408486 | } else if (field->charset() == &my_charset_latin1) { |
| 8668 | 67689 | return (DATA_VARCHAR); | |
| 8669 | } else { | ||
| 8670 | 6340797 | return (DATA_VARMYSQL); | |
| 8671 | } | ||
| 8672 | 1905760 | case MYSQL_TYPE_BIT: | |
| 8673 | case MYSQL_TYPE_STRING: | ||
| 8674 |
2/2✓ Branch 0 taken 15038 times.
✓ Branch 1 taken 1890722 times.
|
1905760 | if (field->binary()) { |
| 8675 | 15038 | return (DATA_FIXBINARY); | |
| 8676 |
2/2✓ Branch 0 taken 11945 times.
✓ Branch 1 taken 1878777 times.
|
1890722 | } else if (field->charset() == &my_charset_latin1) { |
| 8677 | 11945 | return (DATA_CHAR); | |
| 8678 | } else { | ||
| 8679 | 1878777 | return (DATA_MYSQL); | |
| 8680 | } | ||
| 8681 | 19926 | case MYSQL_TYPE_NEWDECIMAL: | |
| 8682 | 19926 | return (DATA_FIXBINARY); | |
| 8683 | 10639066 | case MYSQL_TYPE_LONG: | |
| 8684 | case MYSQL_TYPE_LONGLONG: | ||
| 8685 | case MYSQL_TYPE_TINY: | ||
| 8686 | case MYSQL_TYPE_SHORT: | ||
| 8687 | case MYSQL_TYPE_INT24: | ||
| 8688 | case MYSQL_TYPE_DATE: | ||
| 8689 | case MYSQL_TYPE_YEAR: | ||
| 8690 | case MYSQL_TYPE_NEWDATE: | ||
| 8691 | case MYSQL_TYPE_BOOL: | ||
| 8692 | 10639066 | return (DATA_INT); | |
| 8693 | 593263 | case MYSQL_TYPE_TIME: | |
| 8694 | case MYSQL_TYPE_DATETIME: | ||
| 8695 | case MYSQL_TYPE_TIMESTAMP: | ||
| 8696 | case MYSQL_TYPE_TIME2: | ||
| 8697 | case MYSQL_TYPE_DATETIME2: | ||
| 8698 | case MYSQL_TYPE_TIMESTAMP2: | ||
| 8699 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 593263 times.
|
593263 | switch (field->real_type()) { |
| 8700 | ✗ | case MYSQL_TYPE_TIME: | |
| 8701 | case MYSQL_TYPE_DATETIME: | ||
| 8702 | case MYSQL_TYPE_TIMESTAMP: | ||
| 8703 | ✗ | return (DATA_INT); | |
| 8704 | 593263 | default: | |
| 8705 | assert((ulint)MYSQL_TYPE_DECIMAL < 256); | ||
| 8706 | [[fallthrough]]; | ||
| 8707 | case MYSQL_TYPE_TIME2: | ||
| 8708 | case MYSQL_TYPE_DATETIME2: | ||
| 8709 | case MYSQL_TYPE_TIMESTAMP2: | ||
| 8710 | 593263 | return (DATA_FIXBINARY); | |
| 8711 | } | ||
| 8712 | 72421 | case MYSQL_TYPE_FLOAT: | |
| 8713 | 72421 | return (DATA_FLOAT); | |
| 8714 | 33219 | case MYSQL_TYPE_DOUBLE: | |
| 8715 | 33219 | return (DATA_DOUBLE); | |
| 8716 | ✗ | case MYSQL_TYPE_DECIMAL: | |
| 8717 | ✗ | return (DATA_DECIMAL); | |
| 8718 | 6253 | case MYSQL_TYPE_GEOMETRY: | |
| 8719 | 6253 | return (DATA_GEOMETRY); | |
| 8720 | 2041479 | case MYSQL_TYPE_TINY_BLOB: | |
| 8721 | case MYSQL_TYPE_MEDIUM_BLOB: | ||
| 8722 | case MYSQL_TYPE_BLOB: | ||
| 8723 | case MYSQL_TYPE_LONG_BLOB: | ||
| 8724 | case MYSQL_TYPE_JSON: // JSON fields are stored as BLOBs | ||
| 8725 | 2041479 | return (DATA_BLOB); | |
| 8726 | ✗ | case MYSQL_TYPE_NULL: | |
| 8727 | /* MySQL currently accepts "NULL" datatype, but will | ||
| 8728 | reject such datatype in the next release. We will cope | ||
| 8729 | with it and not trigger assertion failure in 5.1 */ | ||
| 8730 | ✗ | break; | |
| 8731 | 1 | default: | |
| 8732 | 1 | ut_error; | |
| 8733 | } | ||
| 8734 | |||
| 8735 | ✗ | return (0); | |
| 8736 | } | ||
| 8737 | |||
| 8738 | /** Converts a MySQL data-dictionary type to an InnoDB type. Also returns | ||
| 8739 | a few attributes which are useful for precise type calculation. | ||
| 8740 | |||
| 8741 | @note This function is version of get_innobase_type_from_mysql_type() with | ||
| 8742 | added knowledge about how additional attributes calculated (e.g. in | ||
| 8743 | create_table_info_t::create_table_def()) and about behavior of Field | ||
| 8744 | class and its descendats. | ||
| 8745 | |||
| 8746 | @note It allows to get InnoDB generic and precise types directly from MySQL | ||
| 8747 | data-dictionary info, bypassing expensive construction of Field objects. | ||
| 8748 | |||
| 8749 | @param[out] unsigned_flag DATA_UNSIGNED if an 'unsigned type'. | ||
| 8750 | @param[out] binary_type DATA_BINARY_TYPE if a 'binary type'. | ||
| 8751 | @param[out] charset_no Collation id for string types. | ||
| 8752 | @param[in] dd_type MySQL data-dictionary type. | ||
| 8753 | @param[in] field_charset Charset. | ||
| 8754 | @param[in] is_unsigned MySQL data-dictionary unsigned flag. | ||
| 8755 | |||
| 8756 | @return DATA_BINARY, DATA_VARCHAR, ... */ | ||
| 8757 | 682612 | ulint get_innobase_type_from_mysql_dd_type(ulint *unsigned_flag, | |
| 8758 | ulint *binary_type, | ||
| 8759 | ulint *charset_no, | ||
| 8760 | dd::enum_column_types dd_type, | ||
| 8761 | const CHARSET_INFO *field_charset, | ||
| 8762 | bool is_unsigned) { | ||
| 8763 | /* InnoDB's unsigned flag is based on UNSIGNED_FLAG bit in Field::flags. | ||
| 8764 | This bit is unset for Field objects by default. */ | ||
| 8765 | 682612 | *unsigned_flag = 0; | |
| 8766 | /* InnoDB's binary type flag is based on result of Field::binary() call. | ||
| 8767 | The latter returns true by default. */ | ||
| 8768 | 682612 | *binary_type = DATA_BINARY_TYPE; | |
| 8769 | /* InnoDB takes into account charset numbers only for columns which it | ||
| 8770 | considers of string type. */ | ||
| 8771 | 682612 | *charset_no = 0; | |
| 8772 | |||
| 8773 |
5/13✓ Branch 0 taken 6 times.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 676 times.
✓ Branch 4 taken 681849 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
682612 | switch (dd_type) { |
| 8774 | 6 | case dd::enum_column_types::ENUM: | |
| 8775 | case dd::enum_column_types::SET: | ||
| 8776 | /* SQL-layer has its own unsigned flag set to zero, even though | ||
| 8777 | internally this is an unsigned integer type. */ | ||
| 8778 | 6 | *unsigned_flag = DATA_UNSIGNED; | |
| 8779 | /* ENUM and SET are handled as string types by SQL-layer, | ||
| 8780 | hence the charset check. */ | ||
| 8781 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (field_charset != &my_charset_bin) *binary_type = 0; |
| 8782 | 6 | return (DATA_INT); | |
| 8783 | 78 | case dd::enum_column_types::VAR_STRING: /* old <= 4.1 VARCHAR. */ | |
| 8784 | case dd::enum_column_types::VARCHAR: /* new >= 5.0.3 true VARCHAR. */ | ||
| 8785 | 78 | *charset_no = field_charset->number; | |
| 8786 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 76 times.
|
78 | if (field_charset == &my_charset_bin) { |
| 8787 | 2 | return (DATA_BINARY); | |
| 8788 | } else { | ||
| 8789 | 76 | *binary_type = 0; | |
| 8790 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 52 times.
|
76 | if (field_charset == &my_charset_latin1) { |
| 8791 | 24 | return (DATA_VARCHAR); | |
| 8792 | } else { | ||
| 8793 | 52 | return (DATA_VARMYSQL); | |
| 8794 | } | ||
| 8795 | } | ||
| 8796 | ✗ | case dd::enum_column_types::BIT: | |
| 8797 | /* MySQL always sets unsigned flag for both its BIT types. */ | ||
| 8798 | ✗ | *unsigned_flag = DATA_UNSIGNED; | |
| 8799 | ✗ | *charset_no = my_charset_bin.number; | |
| 8800 | ✗ | return (DATA_FIXBINARY); | |
| 8801 | 676 | case dd::enum_column_types::STRING: | |
| 8802 | 676 | *charset_no = field_charset->number; | |
| 8803 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 634 times.
|
676 | if (field_charset == &my_charset_bin) { |
| 8804 | 42 | return (DATA_FIXBINARY); | |
| 8805 | } else { | ||
| 8806 | 634 | *binary_type = 0; | |
| 8807 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 634 times.
|
634 | if (field_charset == &my_charset_latin1) { |
| 8808 | ✗ | return (DATA_CHAR); | |
| 8809 | } else { | ||
| 8810 | 634 | return (DATA_MYSQL); | |
| 8811 | } | ||
| 8812 | } | ||
| 8813 | 681849 | case dd::enum_column_types::DECIMAL: | |
| 8814 | case dd::enum_column_types::FLOAT: | ||
| 8815 | case dd::enum_column_types::DOUBLE: | ||
| 8816 | case dd::enum_column_types::NEWDECIMAL: | ||
| 8817 | case dd::enum_column_types::LONG: | ||
| 8818 | case dd::enum_column_types::LONGLONG: | ||
| 8819 | case dd::enum_column_types::TINY: | ||
| 8820 | case dd::enum_column_types::SHORT: | ||
| 8821 | case dd::enum_column_types::INT24: | ||
| 8822 | /* Types based on Field_num set unsigned flag from value stored | ||
| 8823 | in the data-dictionary (YEAR being the exception). */ | ||
| 8824 |
2/2✓ Branch 0 taken 673926 times.
✓ Branch 1 taken 7923 times.
|
681849 | if (is_unsigned) *unsigned_flag = DATA_UNSIGNED; |
| 8825 | switch (dd_type) { | ||
| 8826 | ✗ | case dd::enum_column_types::DECIMAL: | |
| 8827 | ✗ | return (DATA_DECIMAL); | |
| 8828 | ✗ | case dd::enum_column_types::FLOAT: | |
| 8829 | ✗ | return (DATA_FLOAT); | |
| 8830 | ✗ | case dd::enum_column_types::DOUBLE: | |
| 8831 | ✗ | return (DATA_DOUBLE); | |
| 8832 | ✗ | case dd::enum_column_types::NEWDECIMAL: | |
| 8833 | ✗ | *charset_no = my_charset_bin.number; | |
| 8834 | ✗ | return (DATA_FIXBINARY); | |
| 8835 | 681849 | default: | |
| 8836 | 681849 | break; | |
| 8837 | } | ||
| 8838 | 681849 | return (DATA_INT); | |
| 8839 | ✗ | case dd::enum_column_types::DATE: | |
| 8840 | case dd::enum_column_types::NEWDATE: | ||
| 8841 | case dd::enum_column_types::TIME: | ||
| 8842 | case dd::enum_column_types::DATETIME: | ||
| 8843 | ✗ | return (DATA_INT); | |
| 8844 | ✗ | case dd::enum_column_types::YEAR: | |
| 8845 | case dd::enum_column_types::TIMESTAMP: | ||
| 8846 | /* MySQL always sets unsigned flag for YEAR and old TIMESTAMP type. */ | ||
| 8847 | ✗ | *unsigned_flag = DATA_UNSIGNED; | |
| 8848 | ✗ | return (DATA_INT); | |
| 8849 | ✗ | case dd::enum_column_types::TIME2: | |
| 8850 | case dd::enum_column_types::DATETIME2: | ||
| 8851 | case dd::enum_column_types::TIMESTAMP2: | ||
| 8852 | ✗ | *charset_no = my_charset_bin.number; | |
| 8853 | ✗ | return (DATA_FIXBINARY); | |
| 8854 | ✗ | case dd::enum_column_types::GEOMETRY: | |
| 8855 | /* Field_geom::binary() is always true. */ | ||
| 8856 | ✗ | return (DATA_GEOMETRY); | |
| 8857 | 3 | case dd::enum_column_types::TINY_BLOB: | |
| 8858 | case dd::enum_column_types::MEDIUM_BLOB: | ||
| 8859 | case dd::enum_column_types::BLOB: | ||
| 8860 | case dd::enum_column_types::LONG_BLOB: | ||
| 8861 | 3 | *charset_no = field_charset->number; | |
| 8862 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (field_charset != &my_charset_bin) *binary_type = 0; |
| 8863 | 3 | return (DATA_BLOB); | |
| 8864 | ✗ | case dd::enum_column_types::JSON: | |
| 8865 | /* JSON fields are stored as BLOBs. | ||
| 8866 | Field_json::binary() always returns true even though data in | ||
| 8867 | such columns are stored in UTF8. */ | ||
| 8868 | ✗ | *charset_no = my_charset_utf8mb4_bin.number; | |
| 8869 | ✗ | return (DATA_BLOB); | |
| 8870 | ✗ | case dd::enum_column_types::TYPE_NULL: | |
| 8871 | /* Compatibility with get_innobase_type_from_mysql_type(). */ | ||
| 8872 | ✗ | *charset_no = field_charset->number; | |
| 8873 | ✗ | if (field_charset != &my_charset_bin) *binary_type = 0; | |
| 8874 | ✗ | break; | |
| 8875 | ✗ | default: | |
| 8876 | ✗ | ut_error; | |
| 8877 | } | ||
| 8878 | |||
| 8879 | ✗ | return (0); | |
| 8880 | } | ||
| 8881 | |||
| 8882 | /** Reads an unsigned integer value < 64k from 2 bytes, in the little-endian | ||
| 8883 | storage format. | ||
| 8884 | @return value */ | ||
| 8885 | 126 | static inline uint innobase_read_from_2_little_endian( | |
| 8886 | const uchar *buf) /*!< in: from where to read */ | ||
| 8887 | { | ||
| 8888 | 126 | return ((uint)((ulint)(buf[0]) + 256 * ((ulint)(buf[1])))); | |
| 8889 | } | ||
| 8890 | |||
| 8891 | /** Determines if a field is needed in a m_prebuilt struct 'template'. | ||
| 8892 | @return field to use, or NULL if the field is not needed */ | ||
| 8893 | 1567760803 | static const Field *build_template_needs_field( | |
| 8894 | bool index_contains, /*!< in: | ||
| 8895 | dict_index_contains_col_or_prefix( | ||
| 8896 | index, i) */ | ||
| 8897 | bool read_just_key, /*!< in: true when MySQL calls | ||
| 8898 | ha_innobase::extra with the | ||
| 8899 | argument HA_EXTRA_KEYREAD; it is enough | ||
| 8900 | to read just columns defined in | ||
| 8901 | the index (i.e., no read of the | ||
| 8902 | clustered index record necessary) */ | ||
| 8903 | bool fetch_all_in_key, | ||
| 8904 | /*!< in: true=fetch all fields in | ||
| 8905 | the index */ | ||
| 8906 | bool fetch_primary_key_cols, | ||
| 8907 | /*!< in: true=fetch the | ||
| 8908 | primary key columns */ | ||
| 8909 | dict_index_t *index, /*!< in: InnoDB index to use */ | ||
| 8910 | const TABLE *table, /*!< in: MySQL table object */ | ||
| 8911 | ulint i, /*!< in: field index in InnoDB table */ | ||
| 8912 | ulint num_v) /*!< in: num virtual column so far */ | ||
| 8913 | { | ||
| 8914 | 1567760803 | const Field *field = table->field[i]; | |
| 8915 | |||
| 8916 |
2/2✓ Branch 0 taken 926978434 times.
✓ Branch 1 taken 640782369 times.
|
1567760803 | if (!index_contains) { |
| 8917 |
2/2✓ Branch 0 taken 5090112 times.
✓ Branch 1 taken 921888322 times.
|
926978434 | if (read_just_key) { |
| 8918 | /* If this is a 'key read', we do not need | ||
| 8919 | columns that are not in the key */ | ||
| 8920 | |||
| 8921 | 5090112 | return (nullptr); | |
| 8922 | } | ||
| 8923 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 640782369 times.
|
640782369 | } else if (fetch_all_in_key) { |
| 8924 | /* This field is needed in the query */ | ||
| 8925 | |||
| 8926 | ✗ | return (field); | |
| 8927 | } | ||
| 8928 | |||
| 8929 |
6/6✓ Branch 0 taken 58977217 times.
✓ Branch 1 taken 1503694206 times.
✓ Branch 2 taken 1756739 times.
✓ Branch 3 taken 57220710 times.
✓ Branch 4 taken 1505450929 times.
✓ Branch 5 taken 57220726 times.
|
1621648140 | if (bitmap_is_set(table->read_set, static_cast<uint>(i)) || |
| 8930 | 58977217 | bitmap_is_set(table->write_set, static_cast<uint>(i))) { | |
| 8931 | /* This field is needed in the query */ | ||
| 8932 | |||
| 8933 | 1505450929 | return (field); | |
| 8934 | } | ||
| 8935 | |||
| 8936 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57220705 times.
|
57220726 | ut_ad(i >= num_v); |
| 8937 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 57220705 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57220705 times.
|
57220705 | if (fetch_primary_key_cols && |
| 8938 | ✗ | dict_table_col_in_clustered_key(index->table, i - num_v)) { | |
| 8939 | /* This field is needed in the query */ | ||
| 8940 | |||
| 8941 | ✗ | return (field); | |
| 8942 | } | ||
| 8943 | |||
| 8944 | /* This field is not needed in the query, skip it */ | ||
| 8945 | |||
| 8946 | 57220705 | return (nullptr); | |
| 8947 | } | ||
| 8948 | |||
| 8949 | /** Determines if a field is needed in a m_prebuilt struct 'template'. | ||
| 8950 | @return whether the field is needed for index condition pushdown */ | ||
| 8951 | 41682 | inline bool build_template_needs_field_in_icp( | |
| 8952 | const dict_index_t *index, /*!< in: InnoDB index */ | ||
| 8953 | const row_prebuilt_t *prebuilt, /*!< in: row fetch template */ | ||
| 8954 | bool contains, /*!< in: whether the index contains | ||
| 8955 | column i */ | ||
| 8956 | ulint i, /*!< in: column number */ | ||
| 8957 | bool is_virtual) | ||
| 8958 | /*!< in: a virtual column or not */ | ||
| 8959 | { | ||
| 8960 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41682 times.
|
41682 | ut_ad(contains == dict_index_contains_col_or_prefix(index, i, is_virtual)); |
| 8961 | |||
| 8962 |
2/2✓ Branch 0 taken 41370 times.
✓ Branch 1 taken 312 times.
|
41682 | return (index == prebuilt->index ? contains |
| 8963 | 312 | : dict_index_contains_col_or_prefix( | |
| 8964 | 41994 | prebuilt->index, i, is_virtual)); | |
| 8965 | } | ||
| 8966 | |||
| 8967 | /** Adds a field to a m_prebuilt struct 'template'. | ||
| 8968 | @return the field template */ | ||
| 8969 | 2018805775 | static mysql_row_templ_t *build_template_field( | |
| 8970 | row_prebuilt_t *prebuilt, /*!< in/out: template */ | ||
| 8971 | dict_index_t *clust_index, /*!< in: InnoDB clustered index */ | ||
| 8972 | dict_index_t *index, /*!< in: InnoDB index to use */ | ||
| 8973 | TABLE *table, /*!< in: MySQL table object */ | ||
| 8974 | const Field *field, /*!< in: field in MySQL table */ | ||
| 8975 | ulint i, /*!< in: field index in InnoDB table */ | ||
| 8976 | ulint v_no) /*!< in: field index for virtual col */ | ||
| 8977 | { | ||
| 8978 | mysql_row_templ_t *templ; | ||
| 8979 | const dict_col_t *col; | ||
| 8980 | |||
| 8981 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2018805620 times.
|
2018805775 | ut_ad(clust_index->table == index->table); |
| 8982 | |||
| 8983 | 2018805620 | templ = prebuilt->mysql_template + prebuilt->n_template++; | |
| 8984 | UNIV_MEM_INVALID(templ, sizeof *templ); | ||
| 8985 | |||
| 8986 |
4/4✓ Branch 0 taken 366728 times.
✓ Branch 1 taken 2018438892 times.
✓ Branch 2 taken 310486 times.
✓ Branch 3 taken 56242 times.
|
2018805620 | if (innobase_is_v_fld(field)) { |
| 8987 | 310486 | templ->is_virtual = true; | |
| 8988 | 310486 | col = &dict_table_get_nth_v_col(index->table, v_no)->m_col; | |
| 8989 | } else { | ||
| 8990 | 2018495134 | templ->is_virtual = false; | |
| 8991 | 2018495134 | col = index->table->get_col(i); | |
| 8992 | } | ||
| 8993 | |||
| 8994 |
2/2✓ Branch 0 taken 2018493646 times.
✓ Branch 1 taken 310244 times.
|
2018803890 | if (!templ->is_virtual) { |
| 8995 | 2018493646 | templ->col_no = i; | |
| 8996 | 2018493646 | templ->clust_rec_field_no = dict_col_get_clust_pos(col, clust_index); | |
| 8997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2018498899 times.
|
2018499357 | ut_a(templ->clust_rec_field_no != ULINT_UNDEFINED); |
| 8998 | 2018498899 | templ->rec_prefix_field_no = ULINT_UNDEFINED; | |
| 8999 | |||
| 9000 |
2/2✓ Branch 0 taken 891662378 times.
✓ Branch 1 taken 1126835629 times.
|
2018498899 | if (index->is_clustered()) { |
| 9001 | 891662378 | templ->rec_field_is_prefix = false; | |
| 9002 | 891662378 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 9003 | } else { | ||
| 9004 | /* If we're in a secondary index, keep track of the original index | ||
| 9005 | position even if this is just a prefix non-geometry index; we will use | ||
| 9006 | this later to avoid a cluster index lookup in some cases. */ | ||
| 9007 | |||
| 9008 | 1126835367 | templ->rec_field_no = index->get_col_pos( | |
| 9009 | i, false, false, | ||
| 9010 |
2/2✓ Branch 0 taken 1126835090 times.
✓ Branch 1 taken 277 times.
|
1126835629 | (field->type() == MYSQL_TYPE_GEOMETRY) ? nullptr |
| 9011 | : &templ->rec_prefix_field_no); | ||
| 9012 | 1126833108 | templ->rec_field_is_prefix = | |
| 9013 |
2/2✓ Branch 0 taken 904476250 times.
✓ Branch 1 taken 222356858 times.
|
2031309358 | (templ->rec_field_no == ULINT_UNDEFINED) && |
| 9014 |
2/2✓ Branch 0 taken 1904 times.
✓ Branch 1 taken 904474346 times.
|
904476250 | (templ->rec_prefix_field_no != ULINT_UNDEFINED); |
| 9015 | #ifdef UNIV_DEBUG | ||
| 9016 |
2/2✓ Branch 0 taken 222359246 times.
✓ Branch 1 taken 904473862 times.
|
1126833108 | if (templ->rec_prefix_field_no != ULINT_UNDEFINED) { |
| 9017 | 222359246 | const auto *const field = index->get_field(templ->rec_prefix_field_no); | |
| 9018 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 222359244 times.
|
222359245 | ut_ad(templ->rec_field_is_prefix == (field->prefix_len != 0)); |
| 9019 | } else { | ||
| 9020 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 904474569 times.
|
904473862 | ut_ad(!templ->rec_field_is_prefix); |
| 9021 | } | ||
| 9022 | #endif | ||
| 9023 | } | ||
| 9024 | } else { | ||
| 9025 | 310244 | templ->clust_rec_field_no = v_no; | |
| 9026 | // Prefix optimisation on generated column indexes is not | ||
| 9027 | // currently supported | ||
| 9028 | 310244 | templ->rec_field_is_prefix = false; | |
| 9029 | 310244 | templ->rec_prefix_field_no = ULINT_UNDEFINED; | |
| 9030 |
2/2✓ Branch 0 taken 308648 times.
✓ Branch 1 taken 1838 times.
|
310244 | if (index->is_clustered()) { |
| 9031 | 308648 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 9032 | } else { | ||
| 9033 | 1838 | templ->rec_field_no = index->get_col_pos(v_no, false, true); | |
| 9034 | } | ||
| 9035 | } | ||
| 9036 | |||
| 9037 | /* Set in set_templ_icp(). */ | ||
| 9038 | 2018806677 | templ->icp_rec_field_no = ULINT_UNDEFINED; | |
| 9039 | |||
| 9040 |
2/2✓ Branch 0 taken 893069963 times.
✓ Branch 1 taken 1125734541 times.
|
2018806677 | if (field->is_nullable()) { |
| 9041 | 893069963 | templ->mysql_null_byte_offset = field->null_offset(); | |
| 9042 | |||
| 9043 | 893073490 | templ->mysql_null_bit_mask = (ulint)field->null_bit; | |
| 9044 | } else { | ||
| 9045 | 1125734541 | templ->mysql_null_bit_mask = 0; | |
| 9046 | } | ||
| 9047 | |||
| 9048 | 2018808031 | templ->mysql_col_offset = (ulint)get_field_offset(table, field); | |
| 9049 | 2018805056 | templ->mysql_col_len = (ulint)field->pack_length(); | |
| 9050 |
6/6✓ Branch 0 taken 310486 times.
✓ Branch 1 taken 2018493807 times.
✓ Branch 2 taken 2121 times.
✓ Branch 3 taken 308365 times.
✓ Branch 4 taken 2121 times.
✓ Branch 5 taken 2018802172 times.
|
2018804293 | if (templ->is_virtual && innobase_is_multi_value_fld(field)) { |
| 9051 | 2121 | templ->mysql_mvidx_len = static_cast<ulint>(field->key_length()); | |
| 9052 | 2121 | templ->is_multi_val = true; | |
| 9053 | } else { | ||
| 9054 | 2018802172 | templ->mysql_mvidx_len = 0; | |
| 9055 | 2018802172 | templ->is_multi_val = false; | |
| 9056 | } | ||
| 9057 | 2018804293 | templ->type = col->mtype; | |
| 9058 | 2018804293 | templ->mysql_type = (ulint)field->type(); | |
| 9059 | |||
| 9060 |
2/2✓ Branch 0 taken 414577993 times.
✓ Branch 1 taken 1604226583 times.
|
2018804576 | if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { |
| 9061 | 414577993 | templ->mysql_length_bytes = field->get_length_bytes(); | |
| 9062 | } else { | ||
| 9063 | 1604226583 | templ->mysql_length_bytes = 0; | |
| 9064 | } | ||
| 9065 | |||
| 9066 | 2018807319 | templ->charset = dtype_get_charset_coll(col->prtype); | |
| 9067 | 2018804904 | templ->mbminlen = col->get_mbminlen(); | |
| 9068 | 2018805102 | templ->mbmaxlen = col->get_mbmaxlen(); | |
| 9069 | 2018805955 | templ->is_unsigned = col->prtype & DATA_UNSIGNED; | |
| 9070 | 2018805955 | templ->compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED); | |
| 9071 | 2018805779 | templ->zip_dict_data = field->zip_dict_data; | |
| 9072 | |||
| 9073 |
6/6✓ Branch 0 taken 1126835876 times.
✓ Branch 1 taken 891971445 times.
✓ Branch 2 taken 904477473 times.
✓ Branch 3 taken 222358403 times.
✓ Branch 4 taken 904477386 times.
✓ Branch 5 taken 1114329935 times.
|
2018805779 | if (!index->is_clustered() && templ->rec_field_no == ULINT_UNDEFINED) { |
| 9074 | 904477386 | prebuilt->need_to_access_clustered = true; | |
| 9075 | } | ||
| 9076 | |||
| 9077 | /* For spatial index, we need to access cluster index. */ | ||
| 9078 |
2/2✓ Branch 0 taken 610 times.
✓ Branch 1 taken 2018803155 times.
|
2018807321 | if (dict_index_is_spatial(index)) { |
| 9079 | 610 | prebuilt->need_to_access_clustered = true; | |
| 9080 | } | ||
| 9081 | |||
| 9082 | 2018803765 | if (prebuilt->mysql_prefix_len < | |
| 9083 |
2/2✓ Branch 0 taken 2018713116 times.
✓ Branch 1 taken 90649 times.
|
2018803765 | templ->mysql_col_offset + templ->mysql_col_len) { |
| 9084 | 2018713116 | prebuilt->mysql_prefix_len = templ->mysql_col_offset + templ->mysql_col_len; | |
| 9085 | } | ||
| 9086 | |||
| 9087 |
2/2✓ Branch 0 taken 421239402 times.
✓ Branch 1 taken 1597564602 times.
|
2018803765 | if (DATA_LARGE_MTYPE(templ->type)) { |
| 9088 | 421239402 | prebuilt->templ_contains_blob = true; | |
| 9089 | } | ||
| 9090 | |||
| 9091 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2018804004 times.
|
2018804004 | if (templ->type == DATA_POINT) { |
| 9092 | /* We set this only when it's DATA_POINT, but not | ||
| 9093 | DATA_VAR_POINT */ | ||
| 9094 | ✗ | prebuilt->templ_contains_fixed_point = true; | |
| 9095 | } | ||
| 9096 | |||
| 9097 | 2018804004 | return (templ); | |
| 9098 | } | ||
| 9099 | |||
| 9100 | /** Set Index Condition Push down (ICP) field number in template. | ||
| 9101 | @param[in,out] templ mysql column template | ||
| 9102 | @param[in] index index used to build the template | ||
| 9103 | @param[in] scan_index active index for current scan | ||
| 9104 | @param[in] col_position position of current column */ | ||
| 9105 | 9803 | static void set_templ_icp(mysql_row_templ_t *templ, const dict_index_t *index, | |
| 9106 | const dict_index_t *scan_index, ulint col_position) { | ||
| 9107 |
2/4✓ Branch 0 taken 9803 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9803 times.
|
9803 | if (scan_index == nullptr || templ == nullptr) { |
| 9108 | ✗ | return; | |
| 9109 | } | ||
| 9110 | |||
| 9111 | 9803 | bool is_virtual = templ->is_virtual; | |
| 9112 | 9803 | auto icp_field_no = templ->rec_field_no; | |
| 9113 | |||
| 9114 |
2/2✓ Branch 0 taken 348 times.
✓ Branch 1 taken 9455 times.
|
9803 | if (scan_index != index) { |
| 9115 | /* First, try to find the column position without prefix. */ | ||
| 9116 | 348 | icp_field_no = scan_index->get_col_pos(col_position, false, is_virtual); | |
| 9117 | } | ||
| 9118 | |||
| 9119 | /* Try any prefix of the column. Used in end_range comparison. */ | ||
| 9120 |
2/2✓ Branch 0 taken 399 times.
✓ Branch 1 taken 9404 times.
|
9803 | if (icp_field_no == ULINT_UNDEFINED) { |
| 9121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 399 times.
|
399 | ut_ad(!scan_index->is_clustered()); |
| 9122 | 399 | icp_field_no = scan_index->get_col_pos(col_position, true, is_virtual); | |
| 9123 | } | ||
| 9124 | 9803 | templ->icp_rec_field_no = icp_field_no; | |
| 9125 | } | ||
| 9126 | |||
| 9127 | /** Builds a 'template' to the m_prebuilt struct. The template is used in fast | ||
| 9128 | retrieval of just those column values MySQL needs in its processing. | ||
| 9129 | @param[in] whole_row true if access is needed to a whole row, false if accessing | ||
| 9130 | individual fields is enough */ | ||
| 9131 | 156935290 | void ha_innobase::build_template(bool whole_row) { | |
| 9132 | dict_index_t *index; | ||
| 9133 | dict_index_t *clust_index; | ||
| 9134 | ulint n_fields; | ||
| 9135 | 156935290 | bool fetch_all_in_key = false; | |
| 9136 | 156935290 | bool fetch_primary_key_cols = false; | |
| 9137 | ulint i; | ||
| 9138 | |||
| 9139 |
2/2✓ Branch 0 taken 36809482 times.
✓ Branch 1 taken 120125808 times.
|
156935290 | if (m_prebuilt->select_lock_type == LOCK_X) { |
| 9140 | /* We always retrieve the whole clustered index record if we | ||
| 9141 | use exclusive row level locks, for example, if the read is | ||
| 9142 | done in an UPDATE statement. */ | ||
| 9143 | |||
| 9144 | 36809482 | whole_row = true; | |
| 9145 |
2/2✓ Branch 0 taken 119977018 times.
✓ Branch 1 taken 148790 times.
|
120125808 | } else if (!whole_row) { |
| 9146 |
2/2✓ Branch 0 taken 230 times.
✓ Branch 1 taken 119976788 times.
|
119977018 | if (m_prebuilt->hint_need_to_fetch_extra_cols == ROW_RETRIEVE_ALL_COLS) { |
| 9147 | /* We know we must at least fetch all columns in the | ||
| 9148 | key, or all columns in the table */ | ||
| 9149 | |||
| 9150 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 230 times.
|
230 | if (m_prebuilt->read_just_key) { |
| 9151 | /* MySQL has instructed us that it is enough | ||
| 9152 | to fetch the columns in the key; looks like | ||
| 9153 | MySQL can set this flag also when there is | ||
| 9154 | only a prefix of the column in the key: in | ||
| 9155 | that case we retrieve the whole column from | ||
| 9156 | the clustered index */ | ||
| 9157 | |||
| 9158 | ✗ | fetch_all_in_key = true; | |
| 9159 | } else { | ||
| 9160 | 230 | whole_row = true; | |
| 9161 | } | ||
| 9162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 119976788 times.
|
119976788 | } else if (m_prebuilt->hint_need_to_fetch_extra_cols == |
| 9163 | ROW_RETRIEVE_PRIMARY_KEY) { | ||
| 9164 | /* We must at least fetch all primary key cols. Note | ||
| 9165 | that if the clustered index was internally generated | ||
| 9166 | by InnoDB on the row id (no primary key was | ||
| 9167 | defined), then row_search_for_mysql() will always | ||
| 9168 | retrieve the row id to a special buffer in the | ||
| 9169 | m_prebuilt struct. */ | ||
| 9170 | |||
| 9171 | ✗ | fetch_primary_key_cols = true; | |
| 9172 | } | ||
| 9173 | } | ||
| 9174 | |||
| 9175 | 156935290 | clust_index = m_prebuilt->table->first_index(); | |
| 9176 | |||
| 9177 |
2/2✓ Branch 0 taken 36958601 times.
✓ Branch 1 taken 119976825 times.
|
156935426 | index = whole_row ? clust_index : m_prebuilt->index; |
| 9178 | |||
| 9179 | 156935426 | m_prebuilt->need_to_access_clustered = (index == clust_index); | |
| 9180 | |||
| 9181 | /* Either m_prebuilt->index should be a secondary index, or it | ||
| 9182 | should be the clustered index. */ | ||
| 9183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 156935426 times.
|
156935426 | ut_ad(index->is_clustered() == (index == clust_index)); |
| 9184 | |||
| 9185 | /* Below we check column by column if we need to access | ||
| 9186 | the clustered index. */ | ||
| 9187 | |||
| 9188 | 156935426 | n_fields = (ulint)table->s->fields; /* number of columns */ | |
| 9189 | |||
| 9190 |
2/2✓ Branch 0 taken 3371848 times.
✓ Branch 1 taken 153563578 times.
|
156935426 | if (!m_prebuilt->mysql_template) { |
| 9191 | 3371847 | m_prebuilt->mysql_template = (mysql_row_templ_t *)ut::malloc_withkey( | |
| 9192 | 3371848 | UT_NEW_THIS_FILE_PSI_KEY, n_fields * sizeof(mysql_row_templ_t)); | |
| 9193 | } | ||
| 9194 | |||
| 9195 | #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND) | ||
| 9196 | /* zero-filling for compare contents for debug */ | ||
| 9197 | 156935249 | memset(m_prebuilt->mysql_template, 0, n_fields * sizeof(mysql_row_templ_t)); | |
| 9198 | #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */ | ||
| 9199 | |||
| 9200 | 156935249 | m_prebuilt->template_type = | |
| 9201 |
2/2✓ Branch 0 taken 36958492 times.
✓ Branch 1 taken 119976757 times.
|
156935249 | whole_row ? ROW_MYSQL_WHOLE_ROW : ROW_MYSQL_REC_FIELDS; |
| 9202 | 156935249 | m_prebuilt->null_bitmap_len = table->s->null_bytes; | |
| 9203 | |||
| 9204 | /* Prepare to build m_prebuilt->mysql_template[]. */ | ||
| 9205 | 156935249 | m_prebuilt->templ_contains_blob = false; | |
| 9206 | 156935249 | m_prebuilt->templ_contains_fixed_point = false; | |
| 9207 | 156935249 | m_prebuilt->mysql_prefix_len = 0; | |
| 9208 | 156935249 | m_prebuilt->n_template = 0; | |
| 9209 | 156935249 | m_prebuilt->idx_cond_n_cols = 0; | |
| 9210 | |||
| 9211 | /* Note that in InnoDB, i is the column number in the table. | ||
| 9212 | MySQL calls columns 'fields'. */ | ||
| 9213 | |||
| 9214 |
4/4✓ Branch 0 taken 154915261 times.
✓ Branch 1 taken 2019988 times.
✓ Branch 2 taken 4389 times.
✓ Branch 3 taken 154910872 times.
|
156935249 | if (active_index != MAX_KEY && active_index == pushed_idx_cond_keyno) { |
| 9215 | 4389 | ulint num_v = 0; | |
| 9216 | |||
| 9217 | /* Push down an index condition or an end_range check. */ | ||
| 9218 |
2/2✓ Branch 0 taken 20841 times.
✓ Branch 1 taken 4389 times.
|
25230 | for (i = 0; i < n_fields; i++) { |
| 9219 | bool index_contains; | ||
| 9220 | |||
| 9221 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
20841 | if (innobase_is_v_fld(table->field[i])) { |
| 9222 | 18 | index_contains = dict_index_contains_col_or_prefix(index, num_v, true); | |
| 9223 | } else { | ||
| 9224 | index_contains = | ||
| 9225 | 20823 | dict_index_contains_col_or_prefix(index, i - num_v, false); | |
| 9226 | } | ||
| 9227 | |||
| 9228 | /* Test if an end_range or an index condition | ||
| 9229 | refers to the field. Note that "index" and | ||
| 9230 | "index_contains" may refer to the clustered index. | ||
| 9231 | Index condition pushdown is relative to | ||
| 9232 | m_prebuilt->index (the index that is being | ||
| 9233 | looked up first). */ | ||
| 9234 | |||
| 9235 | /* When join_read_always_key() invokes this | ||
| 9236 | code via handler::ha_index_init() and | ||
| 9237 | ha_innobase::index_init(), end_range is not | ||
| 9238 | yet initialized. Because of that, we must | ||
| 9239 | always check for index_contains, instead of | ||
| 9240 | the subset | ||
| 9241 | field->part_of_key.is_set(active_index) | ||
| 9242 | which would be acceptable if end_range==NULL. */ | ||
| 9243 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
20841 | bool is_v = innobase_is_v_fld(table->field[i]); |
| 9244 |
4/4✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20823 times.
✓ Branch 2 taken 8221 times.
✓ Branch 3 taken 12620 times.
|
20841 | if (build_template_needs_field_in_icp(index, m_prebuilt, index_contains, |
| 9245 | is_v ? num_v : i - num_v, is_v)) { | ||
| 9246 | /* Needed in ICP */ | ||
| 9247 | const Field *field; | ||
| 9248 | mysql_row_templ_t *templ; | ||
| 9249 | |||
| 9250 |
2/2✓ Branch 0 taken 124 times.
✓ Branch 1 taken 8097 times.
|
8221 | if (whole_row) { |
| 9251 | 124 | field = table->field[i]; | |
| 9252 | } else { | ||
| 9253 | 16194 | field = build_template_needs_field( | |
| 9254 | 8097 | index_contains, m_prebuilt->read_just_key, fetch_all_in_key, | |
| 9255 | 8097 | fetch_primary_key_cols, index, table, i, num_v); | |
| 9256 |
2/2✓ Branch 0 taken 466 times.
✓ Branch 1 taken 7631 times.
|
8097 | if (!field) { |
| 9257 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 466 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
466 | if (innobase_is_v_fld(table->field[i])) { |
| 9258 | ✗ | num_v++; | |
| 9259 | } | ||
| 9260 | 466 | continue; | |
| 9261 | } | ||
| 9262 | } | ||
| 9263 | |||
| 9264 | 7755 | templ = build_template_field(m_prebuilt, clust_index, index, table, | |
| 9265 | field, i - num_v, 0); | ||
| 9266 | |||
| 9267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7755 times.
|
7755 | ut_ad(!templ->is_virtual); |
| 9268 | |||
| 9269 | 7755 | m_prebuilt->idx_cond_n_cols++; | |
| 9270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7755 times.
|
7755 | ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template); |
| 9271 | |||
| 9272 | 7755 | auto column_position = i - num_v; | |
| 9273 | |||
| 9274 | 7755 | set_templ_icp(templ, index, m_prebuilt->index, column_position); | |
| 9275 | |||
| 9276 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7755 times.
|
7755 | ut_ad(templ->icp_rec_field_no != ULINT_UNDEFINED); |
| 9277 | |||
| 9278 | /* Index condition pushdown can be used on | ||
| 9279 | all columns of a secondary index, and on | ||
| 9280 | the PRIMARY KEY columns. On the clustered | ||
| 9281 | index, it must never be used on other than | ||
| 9282 | PRIMARY KEY columns, because those columns | ||
| 9283 | may be stored off-page, and we will not | ||
| 9284 | fetch externally stored columns before | ||
| 9285 | checking the index condition. */ | ||
| 9286 | /* TODO: test the above with an assertion | ||
| 9287 | like this. Note that index conditions are | ||
| 9288 | currently pushed down as part of the | ||
| 9289 | "optimizer phase" while end_range is done | ||
| 9290 | as part of the execution phase. Therefore, | ||
| 9291 | we were unable to use an accurate condition | ||
| 9292 | for end_range in the "if" condition above, | ||
| 9293 | and the following assertion would fail. | ||
| 9294 | ut_ad(!(m_prebuilt->index->is_clustered()) | ||
| 9295 | || templ->rec_field_no | ||
| 9296 | < m_prebuilt->index->n_uniq); | ||
| 9297 | */ | ||
| 9298 | } | ||
| 9299 | |||
| 9300 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20347 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
20375 | if (innobase_is_v_fld(table->field[i])) { |
| 9301 | 18 | num_v++; | |
| 9302 | } | ||
| 9303 | } | ||
| 9304 | |||
| 9305 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4389 times.
|
4389 | ut_ad(m_prebuilt->idx_cond_n_cols > 0); |
| 9306 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4389 times.
|
4389 | ut_ad(m_prebuilt->idx_cond_n_cols == m_prebuilt->n_template); |
| 9307 | |||
| 9308 | 4389 | num_v = 0; | |
| 9309 | |||
| 9310 | /* Include the fields that are not needed in index condition | ||
| 9311 | pushdown. */ | ||
| 9312 |
2/2✓ Branch 0 taken 20841 times.
✓ Branch 1 taken 4389 times.
|
25230 | for (i = 0; i < n_fields; i++) { |
| 9313 | mysql_row_templ_t *templ; | ||
| 9314 | bool index_contains; | ||
| 9315 | |||
| 9316 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
20841 | if (innobase_is_v_fld(table->field[i])) { |
| 9317 | 18 | index_contains = dict_index_contains_col_or_prefix(index, num_v, true); | |
| 9318 | } else { | ||
| 9319 | index_contains = | ||
| 9320 | 20823 | dict_index_contains_col_or_prefix(index, i - num_v, false); | |
| 9321 | } | ||
| 9322 | |||
| 9323 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 20813 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 10 times.
|
20841 | bool is_v = innobase_is_v_fld(table->field[i]); |
| 9324 | |||
| 9325 |
4/4✓ Branch 0 taken 18 times.
✓ Branch 1 taken 20823 times.
✓ Branch 2 taken 12620 times.
✓ Branch 3 taken 8221 times.
|
20841 | if (!build_template_needs_field_in_icp(index, m_prebuilt, index_contains, |
| 9326 | is_v ? num_v : i - num_v, is_v)) { | ||
| 9327 | /* Not needed in ICP */ | ||
| 9328 | const Field *field; | ||
| 9329 | |||
| 9330 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 12588 times.
|
12620 | if (whole_row) { |
| 9331 | 32 | field = table->field[i]; | |
| 9332 | } else { | ||
| 9333 | 25176 | field = build_template_needs_field( | |
| 9334 | 12588 | index_contains, m_prebuilt->read_just_key, fetch_all_in_key, | |
| 9335 | 12588 | fetch_primary_key_cols, index, table, i, num_v); | |
| 9336 |
2/2✓ Branch 0 taken 2120 times.
✓ Branch 1 taken 10468 times.
|
12588 | if (!field) { |
| 9337 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2116 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
2120 | if (innobase_is_v_fld(table->field[i])) { |
| 9338 | 4 | num_v++; | |
| 9339 | } | ||
| 9340 | 2120 | continue; | |
| 9341 | } | ||
| 9342 | } | ||
| 9343 | |||
| 9344 | 10500 | templ = build_template_field(m_prebuilt, clust_index, index, table, | |
| 9345 | field, i - num_v, num_v); | ||
| 9346 | |||
| 9347 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 10486 times.
|
10500 | if (templ->is_virtual) { |
| 9348 | 14 | num_v++; | |
| 9349 | } | ||
| 9350 | } | ||
| 9351 | } | ||
| 9352 | |||
| 9353 | 4389 | m_prebuilt->idx_cond = true; | |
| 9354 | 4389 | } else { | |
| 9355 | mysql_row_templ_t *templ; | ||
| 9356 | 156930860 | ulint num_v = 0; | |
| 9357 | /* No index condition pushdown */ | ||
| 9358 | 156930860 | m_prebuilt->idx_cond = false; | |
| 9359 | |||
| 9360 |
2/2✓ Branch 0 taken 2081093656 times.
✓ Branch 1 taken 156930617 times.
|
2238024273 | for (i = 0; i < n_fields; i++) { |
| 9361 | const Field *field; | ||
| 9362 |
4/4✓ Branch 0 taken 573943 times.
✓ Branch 1 taken 2080519713 times.
✓ Branch 2 taken 509169 times.
✓ Branch 3 taken 64774 times.
|
2081093656 | bool is_virtual = innobase_is_v_fld(table->field[i]); |
| 9363 | |||
| 9364 |
2/2✓ Branch 0 taken 513354908 times.
✓ Branch 1 taken 1567738748 times.
|
2081093656 | if (whole_row) { |
| 9365 | /* Even this is whole_row, if the seach is | ||
| 9366 | on a virtual column, and read_just_key is | ||
| 9367 | set, and field is not in this index, we | ||
| 9368 | will not try to fill the value since they | ||
| 9369 | are not stored in such index nor in the | ||
| 9370 | cluster index. */ | ||
| 9371 |
5/6✓ Branch 0 taken 107386 times.
✓ Branch 1 taken 513247522 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 107380 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 513354908 times.
|
513354914 | if (is_virtual && m_prebuilt->read_just_key && |
| 9372 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | !dict_index_contains_col_or_prefix(m_prebuilt->index, num_v, |
| 9373 | true)) { | ||
| 9374 | /* Turn off ROW_MYSQL_WHOLE_ROW */ | ||
| 9375 | ✗ | m_prebuilt->template_type = ROW_MYSQL_REC_FIELDS; | |
| 9376 | ✗ | num_v++; | |
| 9377 | ✗ | continue; | |
| 9378 | } | ||
| 9379 | |||
| 9380 | 513354908 | field = table->field[i]; | |
| 9381 | } else { | ||
| 9382 | bool contain; | ||
| 9383 | |||
| 9384 |
4/4✓ Branch 0 taken 418688 times.
✓ Branch 1 taken 1567320060 times.
✓ Branch 2 taken 401783 times.
✓ Branch 3 taken 16905 times.
|
1567738748 | if (innobase_is_v_fld(table->field[i])) { |
| 9385 | 401783 | contain = dict_index_contains_col_or_prefix(index, num_v, true); | |
| 9386 | } else { | ||
| 9387 | 1567336965 | contain = dict_index_contains_col_or_prefix(index, i - num_v, false); | |
| 9388 | } | ||
| 9389 | |||
| 9390 | 3135479578 | field = build_template_needs_field( | |
| 9391 | 1567738961 | contain, m_prebuilt->read_just_key, fetch_all_in_key, | |
| 9392 | 1567738961 | fetch_primary_key_cols, index, table, i, num_v); | |
| 9393 |
2/2✓ Branch 0 taken 62308172 times.
✓ Branch 1 taken 1505432445 times.
|
1567740617 | if (!field) { |
| 9394 |
2/2✓ Branch 0 taken 198697 times.
✓ Branch 1 taken 62109475 times.
|
62308172 | if (is_virtual) { |
| 9395 | 198697 | num_v++; | |
| 9396 | } | ||
| 9397 | 62308172 | continue; | |
| 9398 | } | ||
| 9399 | } | ||
| 9400 | |||
| 9401 | 2018787353 | templ = build_template_field(m_prebuilt, clust_index, index, table, field, | |
| 9402 | i - num_v, num_v); | ||
| 9403 | |||
| 9404 | /* Virtual columns may have to be read from the secondary index before | ||
| 9405 | evaluating an end-range condition in row_search_end_range_check(). Set | ||
| 9406 | ICP field number for virtual column. */ | ||
| 9407 | 2018785742 | auto scan_index = m_prebuilt->index; | |
| 9408 |
4/4✓ Branch 0 taken 2016133417 times.
✓ Branch 1 taken 2652325 times.
✓ Branch 2 taken 1179175661 times.
✓ Branch 3 taken 836958426 times.
|
2018785742 | bool is_sec_idx = (scan_index != nullptr && !scan_index->is_clustered()); |
| 9409 | |||
| 9410 |
4/4✓ Branch 0 taken 310472 times.
✓ Branch 1 taken 2018475940 times.
✓ Branch 2 taken 2048 times.
✓ Branch 3 taken 308424 times.
|
2018786412 | if (is_virtual && is_sec_idx) { |
| 9411 | 2048 | set_templ_icp(templ, index, scan_index, num_v); | |
| 9412 | } | ||
| 9413 | |||
| 9414 |
2/2✓ Branch 0 taken 310472 times.
✓ Branch 1 taken 2018474769 times.
|
2018785241 | if (templ->is_virtual) { |
| 9415 | 310472 | num_v++; | |
| 9416 | } | ||
| 9417 | } | ||
| 9418 | } | ||
| 9419 | |||
| 9420 |
4/4✓ Branch 0 taken 66718577 times.
✓ Branch 1 taken 90216429 times.
✓ Branch 2 taken 62721945 times.
✓ Branch 3 taken 3996632 times.
|
156935006 | if (index != clust_index && m_prebuilt->need_to_access_clustered) { |
| 9421 | /* Change rec_field_no's to correspond to the clustered index | ||
| 9422 | record */ | ||
| 9423 |
2/2✓ Branch 0 taken 1114787975 times.
✓ Branch 1 taken 62721945 times.
|
1177509920 | for (i = 0; i < m_prebuilt->n_template; i++) { |
| 9424 | 1114787975 | mysql_row_templ_t *templ = &m_prebuilt->mysql_template[i]; | |
| 9425 | |||
| 9426 | 1114787975 | templ->rec_field_no = templ->clust_rec_field_no; | |
| 9427 | } | ||
| 9428 | } | ||
| 9429 | 156935006 | } | |
| 9430 | |||
| 9431 | /** This special handling is really to overcome the limitations of MySQL's | ||
| 9432 | binlogging. We need to eliminate the non-determinism that will arise in | ||
| 9433 | INSERT ... SELECT type of statements, since MySQL binlog only stores the | ||
| 9434 | min value of the autoinc interval. Once that is fixed we can get rid of | ||
| 9435 | the special lock handling. | ||
| 9436 | @return DB_SUCCESS if all OK else error code */ | ||
| 9437 | |||
| 9438 | 8811305 | dberr_t ha_innobase::innobase_lock_autoinc(void) { | |
| 9439 |
1/2✓ Branch 0 taken 8811441 times.
✗ Branch 1 not taken.
|
8811305 | DBUG_TRACE; |
| 9440 | 8811441 | dberr_t error = DB_SUCCESS; | |
| 9441 | 8811441 | long lock_mode = innobase_autoinc_lock_mode; | |
| 9442 | |||
| 9443 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 8811441 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8811428 times.
|
8811441 | ut_ad(!srv_read_only_mode || m_prebuilt->table->is_intrinsic()); |
| 9444 | |||
| 9445 |
6/8✓ Branch 0 taken 8811403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8811409 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7231327 times.
✓ Branch 5 taken 1580082 times.
✓ Branch 6 taken 7231346 times.
✓ Branch 7 taken 1580057 times.
|
8811428 | if (m_prebuilt->table->is_intrinsic() || m_prebuilt->no_autoinc_locking) { |
| 9446 | /* Intrinsic table are not shared across connection | ||
| 9447 | so there is no need to AUTOINC lock the table. | ||
| 9448 | Also we won't use AUTOINC lock if this was requested | ||
| 9449 | explicitly. */ | ||
| 9450 | 7231346 | lock_mode = AUTOINC_NO_LOCKING; | |
| 9451 | } | ||
| 9452 | |||
| 9453 |
3/4✓ Branch 0 taken 8801387 times.
✓ Branch 1 taken 1000 times.
✓ Branch 2 taken 9016 times.
✗ Branch 3 not taken.
|
8811403 | switch (lock_mode) { |
| 9454 | 8801387 | case AUTOINC_NO_LOCKING: | |
| 9455 | /* Acquire only the AUTOINC mutex. */ | ||
| 9456 |
1/2✓ Branch 0 taken 8801445 times.
✗ Branch 1 not taken.
|
8801387 | dict_table_autoinc_lock(m_prebuilt->table); |
| 9457 | 8801445 | break; | |
| 9458 | |||
| 9459 | 1000 | case AUTOINC_NEW_STYLE_LOCKING: | |
| 9460 | /* For simple (single/multi) row INSERTs, we fallback to the | ||
| 9461 | old style only if another transaction has already acquired | ||
| 9462 | the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT | ||
| 9463 | etc. type of statement. */ | ||
| 9464 |
5/6✓ Branch 0 taken 1000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 312 times.
✓ Branch 3 taken 688 times.
✓ Branch 4 taken 688 times.
✓ Branch 5 taken 312 times.
|
1312 | if (thd_sql_command(m_user_thd) == SQLCOM_INSERT || |
| 9465 |
2/4✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 312 times.
|
312 | thd_sql_command(m_user_thd) == SQLCOM_REPLACE) { |
| 9466 | 688 | dict_table_t *ib_table = m_prebuilt->table; | |
| 9467 | |||
| 9468 | /* Acquire the AUTOINC mutex. */ | ||
| 9469 |
1/2✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
|
688 | dict_table_autoinc_lock(ib_table); |
| 9470 | |||
| 9471 |
2/4✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 688 times.
✗ Branch 3 not taken.
|
688 | DEBUG_SYNC_C("innobase_lock_autoinc"); |
| 9472 | |||
| 9473 | /* We need to check that another transaction isn't | ||
| 9474 | already holding the AUTOINC lock on the table. */ | ||
| 9475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
|
688 | if (ib_table->count_by_mode[LOCK_AUTO_INC]) { |
| 9476 | /* Release the mutex to avoid deadlocks. */ | ||
| 9477 | ✗ | dict_table_autoinc_unlock(ib_table); | |
| 9478 | } else { | ||
| 9479 | 688 | break; | |
| 9480 | } | ||
| 9481 | } | ||
| 9482 | /* Fall through to old style locking. */ | ||
| 9483 | [[fallthrough]]; | ||
| 9484 | |||
| 9485 | case AUTOINC_OLD_STYLE_LOCKING: | ||
| 9486 |
2/4✓ Branch 0 taken 9255 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9255 times.
|
9329 | DBUG_EXECUTE_IF("die_if_autoinc_old_lock_style_used", ut_d(ut_error);); |
| 9487 |
1/2✓ Branch 0 taken 9255 times.
✗ Branch 1 not taken.
|
9255 | error = row_lock_table_autoinc_for_mysql(m_prebuilt); |
| 9488 | |||
| 9489 |
2/2✓ Branch 0 taken 9254 times.
✓ Branch 1 taken 1 times.
|
9255 | if (error == DB_SUCCESS) { |
| 9490 | /* Acquire the AUTOINC mutex. */ | ||
| 9491 |
1/2✓ Branch 0 taken 9254 times.
✗ Branch 1 not taken.
|
9254 | dict_table_autoinc_lock(m_prebuilt->table); |
| 9492 | } | ||
| 9493 | 9255 | break; | |
| 9494 | |||
| 9495 | ✗ | default: | |
| 9496 | ✗ | ut_error; | |
| 9497 | } | ||
| 9498 | |||
| 9499 | 8811374 | return error; | |
| 9500 | 8811388 | } | |
| 9501 | |||
| 9502 | /** Store the autoinc value in the table. The autoinc value is only set if | ||
| 9503 | it's greater than the existing autoinc value in the table. | ||
| 9504 | @return DB_SUCCESS if all went well else error code */ | ||
| 9505 | |||
| 9506 | 777795 | dberr_t ha_innobase::innobase_set_max_autoinc( | |
| 9507 | ulonglong auto_inc) /*!< in: value to store */ | ||
| 9508 | { | ||
| 9509 | dberr_t error; | ||
| 9510 | |||
| 9511 | 777795 | error = innobase_lock_autoinc(); | |
| 9512 | |||
| 9513 |
1/2✓ Branch 0 taken 777795 times.
✗ Branch 1 not taken.
|
777795 | if (error == DB_SUCCESS) { |
| 9514 | 777795 | dict_table_autoinc_update_if_greater(m_prebuilt->table, auto_inc); | |
| 9515 | |||
| 9516 | 777795 | dict_table_autoinc_unlock(m_prebuilt->table); | |
| 9517 | } | ||
| 9518 | |||
| 9519 | 777795 | return (error); | |
| 9520 | } | ||
| 9521 | |||
| 9522 | /** Write Row interface optimized for intrinisc table. | ||
| 9523 | @param[in] record a row in MySQL format. | ||
| 9524 | @return 0 on success or error code */ | ||
| 9525 | 5321049 | int ha_innobase::intrinsic_table_write_row(uchar *record) { | |
| 9526 | dberr_t err; | ||
| 9527 | |||
| 9528 | /* No auto-increment support for intrinsic table. */ | ||
| 9529 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 5321049 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5321049 times.
|
5321049 | ut_ad(!(table->next_number_field && record == table->record[0])); |
| 9530 | |||
| 9531 |
2/2✓ Branch 0 taken 5207956 times.
✓ Branch 1 taken 113093 times.
|
5321049 | if (m_prebuilt->mysql_template == nullptr || |
| 9532 |
2/2✓ Branch 0 taken 24417 times.
✓ Branch 1 taken 5183539 times.
|
5207956 | m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) { |
| 9533 | /* Build the template used in converting quickly between | ||
| 9534 | the two database formats */ | ||
| 9535 | 137510 | build_template(true); | |
| 9536 | } | ||
| 9537 | |||
| 9538 | 5321049 | err = row_insert_for_mysql((byte *)record, m_prebuilt); | |
| 9539 | |||
| 9540 | return ( | ||
| 9541 | 5321049 | convert_error_code_to_mysql(err, m_prebuilt->table->flags, m_user_thd)); | |
| 9542 | } | ||
| 9543 | |||
| 9544 | /** Parse out multi-value and store in a multi_value_data struct | ||
| 9545 | @param[in] bv JSON binary that has the mult-value | ||
| 9546 | @param[out] valuep store the parsed out value | ||
| 9547 | @param[in] fld Array Field for the data | ||
| 9548 | @param[in] dfield InnoDB indexed field struct | ||
| 9549 | @param[in] comp if this is new InnoDB row type | ||
| 9550 | @param[in,out] heap heap memory */ | ||
| 9551 | 26241 | static void innobase_store_multi_value_low(json_binary::Value *bv, | |
| 9552 | multi_value_data **valuep, | ||
| 9553 | Field_typed_array *fld, | ||
| 9554 | dfield_t *dfield, ulint comp, | ||
| 9555 | mem_heap_t *heap) { | ||
| 9556 | 26241 | multi_value_data *value = *valuep; | |
| 9557 | byte *buf; | ||
| 9558 | |||
| 9559 | /* Even for single values, there will be an array with 1 element */ | ||
| 9560 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26241 times.
|
26241 | ut_ad(bv->type() == json_binary::Value::ARRAY); |
| 9561 | 26241 | uint32_t elements = bv->element_count(); | |
| 9562 | |||
| 9563 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26241 times.
|
26241 | ut_ad(elements > 0); |
| 9564 | |||
| 9565 |
2/2✓ Branch 0 taken 25559 times.
✓ Branch 1 taken 682 times.
|
26241 | if (value == nullptr) { |
| 9566 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25559 times.
|
25559 | ut_ad(heap != nullptr); |
| 9567 | value = | ||
| 9568 | 25559 | static_cast<multi_value_data *>(mem_heap_zalloc(heap, sizeof(*value))); | |
| 9569 | } | ||
| 9570 | |||
| 9571 |
2/2✓ Branch 0 taken 25560 times.
✓ Branch 1 taken 681 times.
|
26241 | if (elements > value->num_alc) { |
| 9572 | 25560 | value->alloc(elements, false, heap); | |
| 9573 | } | ||
| 9574 | |||
| 9575 | 26241 | buf = reinterpret_cast<byte *>(value->conv_buf); | |
| 9576 | |||
| 9577 | 26241 | value->num_v = elements; | |
| 9578 | |||
| 9579 | 26241 | ulint col_len = fld->key_length(); | |
| 9580 | |||
| 9581 |
2/2✓ Branch 0 taken 254809 times.
✓ Branch 1 taken 26241 times.
|
281050 | for (uint i = 0; i < elements; i++) { |
| 9582 | 254809 | const byte *mysql_data = nullptr; | |
| 9583 |
1/2✓ Branch 0 taken 254809 times.
✗ Branch 1 not taken.
|
254809 | const dtype_t *dtype = dfield_get_type(dfield); |
| 9584 | 254809 | ulint type = dtype->mtype; | |
| 9585 | int64_t val; | ||
| 9586 | |||
| 9587 |
1/2✓ Branch 0 taken 254809 times.
✗ Branch 1 not taken.
|
254809 | json_binary::Value elt = bv->element(i); |
| 9588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 254809 times.
|
254809 | if (elt.type() == json_binary::Value::LITERAL_NULL) { |
| 9589 | ✗ | dfield_set_data(dfield, nullptr, UNIV_SQL_NULL); | |
| 9590 |
2/2✓ Branch 0 taken 253398 times.
✓ Branch 1 taken 1411 times.
|
254809 | } else if (type == DATA_INT) { |
| 9591 | byte data[8]; | ||
| 9592 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 253320 times.
|
253398 | if (elt.type() == json_binary::Value::OPAQUE) { |
| 9593 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
156 | if (elt.field_type() == MYSQL_TYPE_TIME || |
| 9594 |
3/6✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 78 times.
|
156 | elt.field_type() == MYSQL_TYPE_DATETIME || |
| 9595 | 78 | elt.field_type() == MYSQL_TYPE_TIMESTAMP) { | |
| 9596 | /* Newer Mysql temporal types use DATA_FIXBINARY Innodb type */ | ||
| 9597 | ✗ | ut_d(ut_error); /* purecov: inspected */ | |
| 9598 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | } else if (elt.field_type() == MYSQL_TYPE_DATE) { |
| 9599 | /* Temporal data has at most 8 bytes length */ | ||
| 9600 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(), |
| 9601 | 78 | data, fld->decimals()); | |
| 9602 | 78 | mysql_data = data; | |
| 9603 | } else { | ||
| 9604 | ✗ | mysql_data = reinterpret_cast<const byte *>(elt.get_data()); | |
| 9605 | } | ||
| 9606 | } else { | ||
| 9607 | /* Both signed and unsigned ints are handled here. Because there is | ||
| 9608 | an assumption the data passed from server should be always | ||
| 9609 | little-endian one, so need to convert it explicitly here. | ||
| 9610 | @see Field_longlong::store() */ | ||
| 9611 |
2/2✓ Branch 0 taken 253043 times.
✓ Branch 1 taken 277 times.
|
253320 | if (fld->is_unsigned()) { |
| 9612 | 253043 | val = static_cast<int64_t>(elt.get_uint64()); | |
| 9613 | } else { | ||
| 9614 | 277 | val = elt.get_int64(); | |
| 9615 | } | ||
| 9616 | #ifdef WORDS_BIGENDIAN | ||
| 9617 | if (fld->table->s->db_low_byte_first) { | ||
| 9618 | int8store(data, val); | ||
| 9619 | } else | ||
| 9620 | #endif | ||
| 9621 | { | ||
| 9622 | 253320 | longlongstore(data, val); | |
| 9623 | } | ||
| 9624 | 253320 | mysql_data = data; | |
| 9625 | } | ||
| 9626 |
1/2✓ Branch 0 taken 253398 times.
✗ Branch 1 not taken.
|
253398 | row_mysql_store_col_in_innobase_format(dfield, buf, true, mysql_data, |
| 9627 | col_len, comp, false, nullptr, 0, | ||
| 9628 | nullptr); | ||
| 9629 |
4/6✓ Branch 0 taken 1411 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1411 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 525 times.
✓ Branch 5 taken 886 times.
|
1411 | } else if (type == DATA_CHAR || type == DATA_VARCHAR || |
| 9630 | type == DATA_VARMYSQL) { | ||
| 9631 | 525 | mysql_data = (byte *)elt.get_data(); | |
| 9632 | 525 | col_len = (ulint)elt.get_data_length(); | |
| 9633 |
1/2✓ Branch 0 taken 525 times.
✗ Branch 1 not taken.
|
525 | dfield_set_data(dfield, mysql_data, col_len); |
| 9634 |
3/4✓ Branch 0 taken 494 times.
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 494 times.
✗ Branch 3 not taken.
|
886 | } else if (type == DATA_BINARY || type == DATA_FIXBINARY) { |
| 9635 |
1/2✓ Branch 0 taken 886 times.
✗ Branch 1 not taken.
|
886 | if (elt.type() == json_binary::Value::OPAQUE) { |
| 9636 |
3/4✓ Branch 0 taken 392 times.
✓ Branch 1 taken 329 times.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
|
886 | switch (elt.field_type()) { |
| 9637 | 392 | case MYSQL_TYPE_VARCHAR: { | |
| 9638 | 392 | mysql_data = reinterpret_cast<const byte *>(elt.get_data()); | |
| 9639 |
1/2✓ Branch 0 taken 392 times.
✗ Branch 1 not taken.
|
392 | dfield_set_data(dfield, |
| 9640 | 392 | reinterpret_cast<const byte *>(elt.get_data()), | |
| 9641 | 392 | elt.get_data_length()); | |
| 9642 | 392 | break; | |
| 9643 | } | ||
| 9644 | 329 | case MYSQL_TYPE_NEWDECIMAL: { | |
| 9645 | 329 | ut_d(my_decimal d); | |
| 9646 | /* Ensure correct decimal value */ | ||
| 9647 |
2/4✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 329 times.
|
329 | ut_ad(!Json_decimal::convert_from_binary( |
| 9648 | elt.get_data(), elt.get_data_length(), &d)); | ||
| 9649 | /* Ensure binary is of the expected size */ | ||
| 9650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
|
329 | ut_ad(Json_decimal::get_encoded_binary_len(elt.get_data_length()) == |
| 9651 | dfield->type.len); | ||
| 9652 |
1/2✓ Branch 0 taken 329 times.
✗ Branch 1 not taken.
|
329 | dfield_set_data(dfield, |
| 9653 | 329 | Json_decimal::get_encoded_binary(elt.get_data()), | |
| 9654 | 329 | dfield->type.len); | |
| 9655 | 329 | break; | |
| 9656 | 329 | } | |
| 9657 | 165 | case MYSQL_TYPE_TIME: | |
| 9658 | case MYSQL_TYPE_DATE: | ||
| 9659 | case MYSQL_TYPE_DATETIME: | ||
| 9660 | case MYSQL_TYPE_TIMESTAMP: { | ||
| 9661 | /* Temporal data has at most 8 bytes length */ | ||
| 9662 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | Json_datetime::from_packed_to_key(elt.get_data(), elt.field_type(), |
| 9663 | 165 | buf, fld->decimals()); | |
| 9664 | |||
| 9665 |
1/2✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
|
165 | dfield_set_data(dfield, buf, dfield->type.len); |
| 9666 | 165 | break; | |
| 9667 | } | ||
| 9668 | ✗ | default: | |
| 9669 | /* Shouldn't happen */ | ||
| 9670 | ✗ | ut_d(ut_error); /* purecov: inspected */ | |
| 9671 | } | ||
| 9672 | } | ||
| 9673 | 886 | } else { | |
| 9674 | /* not supported */ | ||
| 9675 | ✗ | ut_d(ut_error); /* purecov: inspected */ | |
| 9676 | } | ||
| 9677 | |||
| 9678 | 254809 | value->datap[i] = dfield->data; | |
| 9679 | 254809 | value->data_len[i] = dfield->len; | |
| 9680 | 254809 | buf += sizeof(uint64_t); | |
| 9681 | } | ||
| 9682 | |||
| 9683 | 26241 | *valuep = value; | |
| 9684 | 26241 | } | |
| 9685 | |||
| 9686 | /** Handle the multi-value array, parse the values and store them | ||
| 9687 | @param[in] v JSON binary that has the mult-value | ||
| 9688 | @param[out] value store the parsed out value | ||
| 9689 | @param[in] fld array Field for the data | ||
| 9690 | @param[in] dfield InnoDB indexed field struct | ||
| 9691 | @param[in] comp if this is new InnoDB row type | ||
| 9692 | @param[in,out] heap heap memory | ||
| 9693 | @return true if values are valid and stored, otherwise false */ | ||
| 9694 | 26293 | static inline bool innobase_store_multi_value(json_binary::Value &v, | |
| 9695 | multi_value_data *value, | ||
| 9696 | Field_typed_array *fld, | ||
| 9697 | dfield_t *dfield, bool comp, | ||
| 9698 | mem_heap_t *heap) { | ||
| 9699 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26293 times.
|
26293 | if (v.type() == json_binary::Value::ERROR) { |
| 9700 | /* purecov: begin inspected */ | ||
| 9701 | ✗ | my_error(ER_INVALID_JSON_BINARY_DATA, MYF(0)); | |
| 9702 | ✗ | return (false); | |
| 9703 | /* purecov: end */ | ||
| 9704 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 26272 times.
|
26293 | } else if (v.type() == json_binary::Value::LITERAL_NULL) { |
| 9705 | /* When field is null, json parser creates LETERAL_NULL value. | ||
| 9706 | JSON NULL shouldn't get here in any other way */ | ||
| 9707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | ut_ad(fld->is_null()); |
| 9708 | 21 | dfield_set_null(dfield); | |
| 9709 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 26241 times.
|
26272 | } else if (v.element_count() == 0) { |
| 9710 | 31 | dfield_set_data(dfield, nullptr, UNIV_NO_INDEX_VALUE); | |
| 9711 | } else { | ||
| 9712 | 26241 | innobase_store_multi_value_low(&v, &value, fld, dfield, comp, heap); | |
| 9713 | 26241 | dfield_set_data(dfield, value, UNIV_MULTI_VALUE_ARRAY_MARKER); | |
| 9714 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26241 times.
|
26241 | ut_ad(!value->duplicate()); |
| 9715 | } | ||
| 9716 | |||
| 9717 | 26293 | return (true); | |
| 9718 | } | ||
| 9719 | |||
| 9720 | /** Parse out multi-values from a MySQL record | ||
| 9721 | @param[in] mysql_table MySQL table structure | ||
| 9722 | @param[in] f_idx field index of the multi-value column | ||
| 9723 | @param[in,out] dfield field structure to store parsed multi-value | ||
| 9724 | @param[in,out] value nullptr or the multi-value structure | ||
| 9725 | to store the parsed values | ||
| 9726 | @param[in] old_val old value if exists | ||
| 9727 | @param[in] comp true if InnoDB table uses compact row format | ||
| 9728 | @param[in,out] heap memory heap */ | ||
| 9729 | 812 | void innobase_get_multi_value(const TABLE *mysql_table, ulint f_idx, | |
| 9730 | dfield_t *dfield, multi_value_data *value, | ||
| 9731 | uint old_val, ulint comp, mem_heap_t *heap) { | ||
| 9732 | Field_typed_array *fld; | ||
| 9733 | uint length; | ||
| 9734 | const char *ptr; | ||
| 9735 | |||
| 9736 |
2/4✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 812 times.
|
812 | ut_ad(dfield_check_typed(dfield)); |
| 9737 | |||
| 9738 | 812 | fld = down_cast<Field_typed_array *>(mysql_table->field[f_idx]); | |
| 9739 | |||
| 9740 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 704 times.
|
812 | if (old_val) { |
| 9741 |
1/2✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
|
108 | length = fld->data_length(old_val); |
| 9742 |
1/2✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
|
108 | ptr = fld->get_binary(old_val); |
| 9743 | } else { | ||
| 9744 |
1/2✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
|
704 | length = fld->data_length(); |
| 9745 |
1/2✓ Branch 0 taken 704 times.
✗ Branch 1 not taken.
|
704 | ptr = fld->get_binary(); |
| 9746 | } | ||
| 9747 | |||
| 9748 |
1/2✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
|
812 | json_binary::Value v(json_binary::parse_binary(ptr, length)); |
| 9749 |
4/6✓ Branch 0 taken 21 times.
✓ Branch 1 taken 791 times.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 812 times.
|
812 | ut_ad(v.type() == json_binary::Value::ARRAY || |
| 9750 | v.type() == json_binary::Value::LITERAL_NULL); | ||
| 9751 | |||
| 9752 | ut_d(bool succ =) | ||
| 9753 |
1/2✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
|
812 | innobase_store_multi_value(v, value, fld, dfield, comp, heap); |
| 9754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 812 times.
|
812 | ut_ad(succ); |
| 9755 | 812 | } | |
| 9756 | |||
| 9757 | /** Stores a row in an InnoDB database, to the table specified in this | ||
| 9758 | handle. | ||
| 9759 | @return error code */ | ||
| 9760 | |||
| 9761 | 50929225 | int ha_innobase::write_row(uchar *record) /*!< in: a row in MySQL format */ | |
| 9762 | { | ||
| 9763 | dberr_t error; | ||
| 9764 | 50929225 | int error_result = 0; | |
| 9765 | 50929225 | bool auto_inc_used = false; | |
| 9766 | |||
| 9767 |
1/2✓ Branch 0 taken 50930415 times.
✗ Branch 1 not taken.
|
50929225 | DBUG_TRACE; |
| 9768 | |||
| 9769 | /* Increase the write count of handler */ | ||
| 9770 |
1/2✓ Branch 0 taken 50930270 times.
✗ Branch 1 not taken.
|
50930415 | ha_statistic_increment(&System_status_var::ha_write_count); |
| 9771 | |||
| 9772 |
3/4✓ Branch 0 taken 50930326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5321049 times.
✓ Branch 3 taken 45609277 times.
|
50930270 | if (m_prebuilt->table->is_intrinsic()) { |
| 9773 |
1/2✓ Branch 0 taken 5321049 times.
✗ Branch 1 not taken.
|
5321049 | return intrinsic_table_write_row(record); |
| 9774 | } | ||
| 9775 | |||
| 9776 |
1/2✓ Branch 0 taken 45609312 times.
✗ Branch 1 not taken.
|
45609277 | trx_t *trx = thd_to_trx(m_user_thd); |
| 9777 | |||
| 9778 |
1/2✓ Branch 0 taken 45608737 times.
✗ Branch 1 not taken.
|
45609312 | TrxInInnoDB trx_in_innodb(trx); |
| 9779 | |||
| 9780 |
8/10✓ Branch 0 taken 45609101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45609043 times.
✓ Branch 3 taken 58 times.
✓ Branch 4 taken 45609113 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 45609111 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 45609169 times.
|
45608737 | if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) { |
| 9781 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innobase_rollback(ht, m_user_thd, false); |
| 9782 | |||
| 9783 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 9784 | } | ||
| 9785 | |||
| 9786 | /* Validation checks before we commence write_row operation. */ | ||
| 9787 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 45609134 times.
|
45609169 | if (high_level_read_only) { |
| 9788 |
2/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
|
35 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 9789 | 35 | return HA_ERR_TABLE_READONLY; | |
| 9790 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45609134 times.
|
45609134 | } else if (m_prebuilt->trx != trx) { |
| 9791 | ✗ | ib::error(ER_IB_MSG_558) << "The transaction object for the table handle is" | |
| 9792 | ✗ | " at " | |
| 9793 | ✗ | << static_cast<const void *>(m_prebuilt->trx) | |
| 9794 | ✗ | << ", but for the current thread it is at " | |
| 9795 | ✗ | << static_cast<const void *>(trx); | |
| 9796 | |||
| 9797 | ✗ | fputs("InnoDB: Dump of 200 bytes around m_prebuilt: ", stderr); | |
| 9798 | ✗ | ut_print_buf(stderr, ((const byte *)m_prebuilt) - 100, 200); | |
| 9799 | ✗ | fputs("\nInnoDB: Dump of 200 bytes around ha_data: ", stderr); | |
| 9800 | ✗ | ut_print_buf(stderr, ((const byte *)trx) - 100, 200); | |
| 9801 | ✗ | putc('\n', stderr); | |
| 9802 | ✗ | ut_error; | |
| 9803 |
3/4✓ Branch 0 taken 45608250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2096367 times.
✓ Branch 3 taken 43511883 times.
|
45609134 | } else if (!trx_is_started(trx)) { |
| 9804 | 2096367 | ++trx->will_lock; | |
| 9805 | } | ||
| 9806 | |||
| 9807 | /* Handling of Auto-Increment Columns. */ | ||
| 9808 |
3/4✓ Branch 0 taken 14579371 times.
✓ Branch 1 taken 31028879 times.
✓ Branch 2 taken 14579402 times.
✗ Branch 3 not taken.
|
45608250 | if (table->next_number_field && record == table->record[0]) { |
| 9809 | /* Reset the error code before calling | ||
| 9810 | innobase_get_auto_increment(). */ | ||
| 9811 | 14579402 | m_prebuilt->autoinc_error = DB_SUCCESS; | |
| 9812 | |||
| 9813 |
1/2✓ Branch 0 taken 14579463 times.
✗ Branch 1 not taken.
|
14579402 | error_result = update_auto_increment(); |
| 9814 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 14579452 times.
|
14579463 | if (error_result) { |
| 9815 | /* We don't want to mask autoinc overflow errors. */ | ||
| 9816 | |||
| 9817 | /* Handle the case where the AUTOINC sub-system | ||
| 9818 | failed during initialization. */ | ||
| 9819 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (m_prebuilt->autoinc_error == DB_UNSUPPORTED) { |
| 9820 | ✗ | error_result = ER_AUTOINC_READ_FAILED; | |
| 9821 | /* Set the error message to report too. */ | ||
| 9822 | ✗ | my_error(ER_AUTOINC_READ_FAILED, MYF(0)); | |
| 9823 | ✗ | goto func_exit; | |
| 9824 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
|
11 | } else if (m_prebuilt->autoinc_error != DB_SUCCESS) { |
| 9825 | 1 | error = m_prebuilt->autoinc_error; | |
| 9826 | 1 | goto report_error; | |
| 9827 | } | ||
| 9828 | |||
| 9829 | /* MySQL errors are passed straight back. */ | ||
| 9830 | 10 | goto func_exit; | |
| 9831 | } | ||
| 9832 | |||
| 9833 | 14579452 | auto_inc_used = true; | |
| 9834 | } | ||
| 9835 | |||
| 9836 | /* Prepare INSERT graph that will be executed for actual INSERT | ||
| 9837 | (This is a one time operation) */ | ||
| 9838 |
2/2✓ Branch 0 taken 45391308 times.
✓ Branch 1 taken 216992 times.
|
45608300 | if (m_prebuilt->mysql_template == nullptr || |
| 9839 |
2/2✓ Branch 0 taken 749233 times.
✓ Branch 1 taken 44642075 times.
|
45391308 | m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) { |
| 9840 | /* Build the template used in converting quickly between | ||
| 9841 | the two database formats */ | ||
| 9842 | |||
| 9843 |
1/2✓ Branch 0 taken 966460 times.
✗ Branch 1 not taken.
|
966225 | build_template(true); |
| 9844 | } | ||
| 9845 | |||
| 9846 |
1/2✓ Branch 0 taken 45608398 times.
✗ Branch 1 not taken.
|
45608535 | error = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 9847 | |||
| 9848 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45608398 times.
|
45608398 | if (error != DB_SUCCESS) { |
| 9849 | ✗ | goto report_error; | |
| 9850 | } | ||
| 9851 | |||
| 9852 | /* Execute insert graph that will result in actual insert. */ | ||
| 9853 |
1/2✓ Branch 0 taken 45609192 times.
✗ Branch 1 not taken.
|
45608398 | error = row_insert_for_mysql((byte *)record, m_prebuilt); |
| 9854 | |||
| 9855 |
3/4✓ Branch 0 taken 40351370 times.
✓ Branch 1 taken 5258010 times.
✓ Branch 2 taken 40351409 times.
✗ Branch 3 not taken.
|
45609192 | DEBUG_SYNC(m_user_thd, "ib_after_row_insert"); |
| 9856 | |||
| 9857 | /* Handling of errors related to auto-increment. */ | ||
| 9858 |
2/2✓ Branch 0 taken 14579480 times.
✓ Branch 1 taken 31029939 times.
|
45609419 | if (auto_inc_used) { |
| 9859 | ulonglong auto_inc; | ||
| 9860 | ulonglong col_max_value; | ||
| 9861 | |||
| 9862 | /* Note the number of rows processed for this statement, used | ||
| 9863 | by get_auto_increment() to determine the number of AUTO-INC | ||
| 9864 | values to reserve. This is only useful for a mult-value INSERT | ||
| 9865 | and is a statement level counter. */ | ||
| 9866 |
2/2✓ Branch 0 taken 13805909 times.
✓ Branch 1 taken 773571 times.
|
14579480 | if (trx->n_autoinc_rows > 0) { |
| 9867 | 13805909 | --trx->n_autoinc_rows; | |
| 9868 | } | ||
| 9869 | |||
| 9870 | /* We need the upper limit of the col type to check for | ||
| 9871 | whether we update the table autoinc counter or not. */ | ||
| 9872 |
1/2✓ Branch 0 taken 14579480 times.
✗ Branch 1 not taken.
|
14579480 | col_max_value = table->next_number_field->get_max_int_value(); |
| 9873 | |||
| 9874 | /* Get the value that MySQL attempted to store in the table. */ | ||
| 9875 |
1/2✓ Branch 0 taken 14579481 times.
✗ Branch 1 not taken.
|
14579480 | auto_inc = table->next_number_field->val_int(); |
| 9876 | |||
| 9877 |
3/3✓ Branch 0 taken 250 times.
✓ Branch 1 taken 14579213 times.
✓ Branch 2 taken 18 times.
|
14579481 | switch (error) { |
| 9878 | 250 | case DB_DUPLICATE_KEY: | |
| 9879 | |||
| 9880 | /* A REPLACE command and LOAD DATA INFILE REPLACE | ||
| 9881 | handle a duplicate key error themselves, but we | ||
| 9882 | must update the autoinc counter if we are performing | ||
| 9883 | those statements. */ | ||
| 9884 | |||
| 9885 |
4/5✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 94 times.
✓ Branch 4 taken 150 times.
|
250 | switch (thd_sql_command(m_user_thd)) { |
| 9886 | 6 | case SQLCOM_LOAD: | |
| 9887 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!m_prebuilt->allow_duplicates()) { |
| 9888 | ✗ | break; | |
| 9889 | } | ||
| 9890 | |||
| 9891 | case SQLCOM_REPLACE: | ||
| 9892 | case SQLCOM_INSERT_SELECT: | ||
| 9893 | case SQLCOM_REPLACE_SELECT: | ||
| 9894 | 100 | goto set_max_autoinc; | |
| 9895 | |||
| 9896 | 150 | default: | |
| 9897 | 150 | break; | |
| 9898 | } | ||
| 9899 | |||
| 9900 | 150 | break; | |
| 9901 | |||
| 9902 | 14579213 | case DB_SUCCESS: | |
| 9903 | /* If the actual value inserted is greater than | ||
| 9904 | the upper limit of the interval, then we try and | ||
| 9905 | update the table upper limit. Note: last_value | ||
| 9906 | will be 0 if get_auto_increment() was not called. */ | ||
| 9907 | |||
| 9908 |
2/2✓ Branch 0 taken 777034 times.
✓ Branch 1 taken 13802179 times.
|
14579213 | if (auto_inc >= m_prebuilt->autoinc_last_value) { |
| 9909 | 777034 | set_max_autoinc: | |
| 9910 | /* This should filter out the negative | ||
| 9911 | values set explicitly by the user. */ | ||
| 9912 |
2/2✓ Branch 0 taken 776955 times.
✓ Branch 1 taken 179 times.
|
777134 | if (auto_inc <= col_max_value) { |
| 9913 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 776955 times.
|
776955 | ut_a(m_prebuilt->autoinc_increment > 0); |
| 9914 | |||
| 9915 | ulonglong offset; | ||
| 9916 | ulonglong increment; | ||
| 9917 | dberr_t err; | ||
| 9918 | |||
| 9919 | 776955 | offset = m_prebuilt->autoinc_offset; | |
| 9920 | 776955 | increment = m_prebuilt->autoinc_increment; | |
| 9921 | |||
| 9922 |
1/2✓ Branch 0 taken 776955 times.
✗ Branch 1 not taken.
|
776955 | auto_inc = innobase_next_autoinc(auto_inc, 1, increment, offset, |
| 9923 | col_max_value); | ||
| 9924 | |||
| 9925 |
1/2✓ Branch 0 taken 776955 times.
✗ Branch 1 not taken.
|
776955 | err = innobase_set_max_autoinc(auto_inc); |
| 9926 | |||
| 9927 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 776955 times.
|
776955 | if (err != DB_SUCCESS) { |
| 9928 | ✗ | error = err; | |
| 9929 | } | ||
| 9930 | } | ||
| 9931 | } | ||
| 9932 | 14579313 | break; | |
| 9933 | 18 | default: | |
| 9934 | 18 | break; | |
| 9935 | } | ||
| 9936 | } | ||
| 9937 | |||
| 9938 |
1/2✓ Branch 0 taken 45609411 times.
✗ Branch 1 not taken.
|
45609420 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 9939 | |||
| 9940 | 45609412 | report_error: | |
| 9941 | /* Cleanup and exit. */ | ||
| 9942 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 45609386 times.
|
45609412 | if (error == DB_TABLESPACE_DELETED) { |
| 9943 | 26 | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 9944 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | table->s->table_name.str); |
| 9945 | } | ||
| 9946 | |||
| 9947 | error_result = | ||
| 9948 |
1/2✓ Branch 0 taken 45609301 times.
✗ Branch 1 not taken.
|
45609412 | convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd); |
| 9949 | |||
| 9950 |
2/2✓ Branch 0 taken 45609300 times.
✓ Branch 1 taken 1 times.
|
45609301 | if (error_result == HA_FTS_INVALID_DOCID) { |
| 9951 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(HA_FTS_INVALID_DOCID, MYF(0)); |
| 9952 | } | ||
| 9953 | |||
| 9954 | 45609300 | func_exit: | |
| 9955 | |||
| 9956 |
1/2✓ Branch 0 taken 45609400 times.
✗ Branch 1 not taken.
|
45609311 | innobase_active_small(); |
| 9957 | |||
| 9958 | 45609400 | return error_result; | |
| 9959 | 50930486 | } | |
| 9960 | |||
| 9961 | /** Fill the update vector's "old_vrow" field for those non-updated, | ||
| 9962 | but indexed columns. Such columns could stil present in the virtual | ||
| 9963 | index rec fields even if they are not updated (some other fields updated), | ||
| 9964 | so needs to be logged. | ||
| 9965 | @param[in] prebuilt InnoDB prebuilt struct | ||
| 9966 | @param[in,out] vfield field to filled | ||
| 9967 | @param[in] o_len actual column length | ||
| 9968 | @param[in] old_mysql_row_col MySQL old field ptr | ||
| 9969 | @param[in] col_pack_len MySQL field col length | ||
| 9970 | @param[in,out] buf buffer for a converted integer value | ||
| 9971 | @return used buffer ptr from row_mysql_store_col_in_innobase_format() */ | ||
| 9972 | 3637 | static byte *innodb_fill_old_vcol_val(row_prebuilt_t *prebuilt, | |
| 9973 | dfield_t *vfield, ulint o_len, | ||
| 9974 | const byte *old_mysql_row_col, | ||
| 9975 | ulint col_pack_len, byte *buf) { | ||
| 9976 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3637 times.
|
3637 | ut_ad(dfield_check_typed(vfield)); |
| 9977 | |||
| 9978 |
2/2✓ Branch 0 taken 3621 times.
✓ Branch 1 taken 16 times.
|
3637 | if (o_len != UNIV_SQL_NULL) { |
| 9979 | 3621 | buf = row_mysql_store_col_in_innobase_format( | |
| 9980 | vfield, buf, true, old_mysql_row_col, col_pack_len, | ||
| 9981 | 3621 | dict_table_is_comp(prebuilt->table), false, nullptr, 0, nullptr); | |
| 9982 | } else { | ||
| 9983 | 16 | dfield_set_null(vfield); | |
| 9984 | } | ||
| 9985 | |||
| 9986 | 3637 | return (buf); | |
| 9987 | } | ||
| 9988 | |||
| 9989 | /** Parse out multi-values from both old and new MySQL records, | ||
| 9990 | at the meantime, calculate the difference between two records. | ||
| 9991 | @param[in] mysql_table MySQL table structure | ||
| 9992 | @param[in] field_idx field index of the multi-value column | ||
| 9993 | @param[in,out] old_field field structure to store the parsed old value | ||
| 9994 | @param[in,out] new_field field structure to store the parsed new value | ||
| 9995 | @param[in] old_value old value to parse | ||
| 9996 | @param[in] comp true if InnoDB table uses compact row format | ||
| 9997 | @param[in,out] heap memory heap */ | ||
| 9998 | 77 | static void innobase_get_multi_value_and_diff( | |
| 9999 | const TABLE *mysql_table, ulint field_idx, dfield_t *old_field, | ||
| 10000 | dfield_t *new_field, uint old_value, ulint comp, mem_heap_t *heap) { | ||
| 10001 | Field_typed_array *fld; | ||
| 10002 | 77 | const char *old_ptr = nullptr; | |
| 10003 | 77 | const char *new_ptr = nullptr; | |
| 10004 | uint old_len; | ||
| 10005 | uint new_len; | ||
| 10006 | |||
| 10007 | 77 | fld = down_cast<Field_typed_array *>(mysql_table->field[field_idx]); | |
| 10008 | |||
| 10009 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | old_ptr = fld->get_binary(old_value); |
| 10010 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | old_len = fld->get_length(old_value); |
| 10011 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | new_ptr = fld->get_binary(); |
| 10012 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | new_len = fld->get_length(); |
| 10013 | |||
| 10014 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | json_binary::Value old_v(json_binary::parse_binary(old_ptr, old_len)); |
| 10015 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | json_binary::Value new_v(json_binary::parse_binary(new_ptr, new_len)); |
| 10016 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | ut_ad(old_v.type() == json_binary::Value::ARRAY); |
| 10017 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | ut_ad(new_v.type() == json_binary::Value::ARRAY); |
| 10018 | |||
| 10019 | ut_d(bool succ1 =) | ||
| 10020 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | innobase_store_multi_value(old_v, nullptr, fld, old_field, comp, heap); |
| 10021 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | ut_ad(succ1); |
| 10022 | ut_d(bool succ2 =) | ||
| 10023 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | innobase_store_multi_value(new_v, nullptr, fld, new_field, comp, heap); |
| 10024 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | ut_ad(succ2); |
| 10025 | |||
| 10026 |
2/4✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
|
77 | ut_ad(!dfield_is_null(old_field)); |
| 10027 |
2/4✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
|
77 | ut_ad(!dfield_is_null(new_field)); |
| 10028 | /* If no indexed value, then no need to get the difference */ | ||
| 10029 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | if (old_field->len == UNIV_NO_INDEX_VALUE || |
| 10030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | new_field->len == UNIV_NO_INDEX_VALUE) { |
| 10031 | ✗ | return; | |
| 10032 | } | ||
| 10033 | |||
| 10034 | /* Now old_field and new_field are having both multi-value data, in the | ||
| 10035 | same sequence with data in old_v and new_v, which are also sorted in | ||
| 10036 | ascending order. */ | ||
| 10037 | |||
| 10038 | 77 | uint old_counter = 0; | |
| 10039 | 77 | uint new_counter = 0; | |
| 10040 | 77 | multi_value_data *old_mv = static_cast<multi_value_data *>(old_field->data); | |
| 10041 | 77 | multi_value_data *new_mv = static_cast<multi_value_data *>(new_field->data); | |
| 10042 | |||
| 10043 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | old_mv->alloc_bitset(heap); |
| 10044 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | new_mv->alloc_bitset(heap); |
| 10045 | |||
| 10046 |
6/6✓ Branch 0 taken 270 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 263 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 263 times.
✓ Branch 5 taken 77 times.
|
610 | while (old_counter < old_v.element_count() && |
| 10047 | 270 | new_counter < new_v.element_count()) { | |
| 10048 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 263 times.
|
263 | ut_ad(old_counter < old_mv->num_v); |
| 10049 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 263 times.
|
263 | ut_ad(new_counter < new_mv->num_v); |
| 10050 | |||
| 10051 |
3/6✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 263 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 263 times.
✗ Branch 5 not taken.
|
263 | int res = old_v.element(old_counter).eq(new_v.element(new_counter)); |
| 10052 |
2/2✓ Branch 0 taken 82 times.
✓ Branch 1 taken 181 times.
|
263 | if (res == 0) { |
| 10053 |
1/2✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
|
82 | old_mv->bitset->set(old_counter++, false); |
| 10054 |
1/2✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
|
82 | new_mv->bitset->set(new_counter++, false); |
| 10055 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 31 times.
|
181 | } else if (res < 0) { |
| 10056 | 150 | ++old_counter; | |
| 10057 | } else { | ||
| 10058 | 31 | ++new_counter; | |
| 10059 | } | ||
| 10060 | } | ||
| 10061 | } | ||
| 10062 | |||
| 10063 | /** Checks which fields have changed in a row and stores information | ||
| 10064 | of them to an update vector. | ||
| 10065 | @return DB_SUCCESS or error code */ | ||
| 10066 | 11737974 | static dberr_t calc_row_difference( | |
| 10067 | upd_t *uvect, /*!< in/out: update vector */ | ||
| 10068 | const uchar *old_row, /*!< in: old row in MySQL format */ | ||
| 10069 | uchar *new_row, /*!< in: new row in MySQL format */ | ||
| 10070 | TABLE *table, /*!< in: table in MySQL data | ||
| 10071 | dictionary */ | ||
| 10072 | uchar *upd_buff, /*!< in: buffer to use */ | ||
| 10073 | ulint buff_len, /*!< in: buffer length */ | ||
| 10074 | row_prebuilt_t *prebuilt, /*!< in: InnoDB prebuilt struct */ | ||
| 10075 | THD *thd) /*!< in: user thread */ | ||
| 10076 | { | ||
| 10077 | 11737974 | uchar *original_upd_buff = upd_buff; | |
| 10078 | Field *field; | ||
| 10079 | enum_field_types field_mysql_type; | ||
| 10080 | uint n_fields; | ||
| 10081 | ulint o_len; | ||
| 10082 | ulint n_len; | ||
| 10083 | ulint col_pack_len; | ||
| 10084 | const byte *new_mysql_row_col; | ||
| 10085 | const byte *old_mysql_row_col; | ||
| 10086 | const byte *o_ptr; | ||
| 10087 | const byte *n_ptr; | ||
| 10088 | byte *buf; | ||
| 10089 | upd_field_t *ufield; | ||
| 10090 | ulint col_type; | ||
| 10091 | 11737974 | ulint n_changed = 0; | |
| 10092 | 11737974 | dfield_t dfield; | |
| 10093 | dict_index_t *clust_index; | ||
| 10094 | uint i; | ||
| 10095 | 11737980 | bool changes_fts_column = false; | |
| 10096 | 11737980 | bool changes_fts_doc_col = false; | |
| 10097 |
1/2✓ Branch 0 taken 11737979 times.
✗ Branch 1 not taken.
|
11737980 | trx_t *trx = thd_to_trx(thd); |
| 10098 | 11737979 | doc_id_t doc_id = FTS_NULL_DOC_ID; | |
| 10099 | 11737979 | ulint comp = 0; | |
| 10100 | 11737979 | ulint num_v = 0; | |
| 10101 | |||
| 10102 |
5/8✓ Branch 0 taken 4 times.
✓ Branch 1 taken 11737975 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11737981 times.
|
11737979 | ut_ad(!srv_read_only_mode || prebuilt->table->is_intrinsic()); |
| 10103 | |||
| 10104 |
1/2✓ Branch 0 taken 11737977 times.
✗ Branch 1 not taken.
|
11737981 | comp = dict_table_is_comp(prebuilt->table); |
| 10105 | |||
| 10106 | 11737977 | n_fields = table->s->fields; | |
| 10107 |
1/2✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
|
11737977 | clust_index = prebuilt->table->first_index(); |
| 10108 | |||
| 10109 | /* We use upd_buff to convert changed fields */ | ||
| 10110 | 11737981 | buf = (byte *)upd_buff; | |
| 10111 | |||
| 10112 |
2/2✓ Branch 0 taken 135319846 times.
✓ Branch 1 taken 11738040 times.
|
147057886 | for (i = 0; i < n_fields; i++) { |
| 10113 | 135319846 | dfield.reset(); | |
| 10114 | |||
| 10115 | 135319903 | field = table->field[i]; | |
| 10116 |
4/4✓ Branch 0 taken 141191 times.
✓ Branch 1 taken 135178712 times.
✓ Branch 2 taken 82320 times.
✓ Branch 3 taken 58871 times.
|
135319903 | bool is_virtual = innobase_is_v_fld(field); |
| 10117 |
1/2✓ Branch 0 taken 135319900 times.
✗ Branch 1 not taken.
|
135319903 | bool is_multi_value = innobase_is_multi_value_fld(field); |
| 10118 | dict_col_t *col; | ||
| 10119 | |||
| 10120 |
2/2✓ Branch 0 taken 82320 times.
✓ Branch 1 taken 135237580 times.
|
135319900 | if (is_virtual) { |
| 10121 | 82320 | col = &prebuilt->table->v_cols[num_v].m_col; | |
| 10122 | } else { | ||
| 10123 | 135237580 | col = &prebuilt->table->cols[i - num_v]; | |
| 10124 | } | ||
| 10125 | |||
| 10126 | 135319900 | o_ptr = (const byte *)old_row + get_field_offset(table, field); | |
| 10127 | 135319901 | n_ptr = (const byte *)new_row + get_field_offset(table, field); | |
| 10128 | |||
| 10129 | /* Use new_mysql_row_col and col_pack_len save the values */ | ||
| 10130 | |||
| 10131 | 135319895 | new_mysql_row_col = n_ptr; | |
| 10132 | 135319895 | old_mysql_row_col = o_ptr; | |
| 10133 |
1/2✓ Branch 0 taken 135319877 times.
✗ Branch 1 not taken.
|
135319895 | col_pack_len = field->pack_length(); |
| 10134 | |||
| 10135 | 135319877 | o_len = col_pack_len; | |
| 10136 | 135319877 | n_len = col_pack_len; | |
| 10137 | |||
| 10138 | /* We use o_ptr and n_ptr to dig up the actual data for | ||
| 10139 | comparison. */ | ||
| 10140 | |||
| 10141 |
1/2✓ Branch 0 taken 135319873 times.
✗ Branch 1 not taken.
|
135319877 | field_mysql_type = field->type(); |
| 10142 | |||
| 10143 | 135319873 | col_type = col->mtype; | |
| 10144 | |||
| 10145 | /* Reset the type to BLOB for multi-value field, since server may | ||
| 10146 | keep it as non-BLOB one. */ | ||
| 10147 |
2/2✓ Branch 0 taken 193 times.
✓ Branch 1 taken 135319680 times.
|
135319873 | if (is_multi_value) { |
| 10148 | 193 | col_type = DATA_BLOB; | |
| 10149 | } | ||
| 10150 | |||
| 10151 |
3/3✓ Branch 0 taken 28475150 times.
✓ Branch 1 taken 16442025 times.
✓ Branch 2 taken 90402698 times.
|
135319873 | switch (col_type) { |
| 10152 | 28475150 | case DATA_BLOB: | |
| 10153 | case DATA_POINT: | ||
| 10154 | case DATA_VAR_POINT: | ||
| 10155 | case DATA_GEOMETRY: | ||
| 10156 | /* Do not compress blob column while comparing */ | ||
| 10157 |
1/2✓ Branch 0 taken 28475151 times.
✗ Branch 1 not taken.
|
28475150 | o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len, false, nullptr, 0, |
| 10158 | &prebuilt->compress_heap); | ||
| 10159 |
1/2✓ Branch 0 taken 28475152 times.
✗ Branch 1 not taken.
|
28475151 | n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len, false, nullptr, 0, |
| 10160 | &prebuilt->compress_heap); | ||
| 10161 | |||
| 10162 | 28475152 | break; | |
| 10163 | |||
| 10164 | 16442025 | case DATA_VARCHAR: | |
| 10165 | case DATA_BINARY: | ||
| 10166 | case DATA_VARMYSQL: | ||
| 10167 |
1/2✓ Branch 0 taken 16442027 times.
✗ Branch 1 not taken.
|
16442025 | if (field_mysql_type == MYSQL_TYPE_VARCHAR) { |
| 10168 | /* This is a >= 5.0.3 type true VARCHAR where | ||
| 10169 | the real payload data length is stored in | ||
| 10170 | 1 or 2 bytes */ | ||
| 10171 | |||
| 10172 | 32884052 | o_ptr = row_mysql_read_true_varchar(&o_len, o_ptr, | |
| 10173 |
2/4✓ Branch 0 taken 16442023 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16442029 times.
✗ Branch 3 not taken.
|
16442027 | (ulint)field->get_length_bytes()); |
| 10174 | |||
| 10175 | 16442031 | n_ptr = row_mysql_read_true_varchar(&n_len, n_ptr, | |
| 10176 |
2/4✓ Branch 0 taken 16442031 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16442031 times.
✗ Branch 3 not taken.
|
16442029 | (ulint)field->get_length_bytes()); |
| 10177 | } | ||
| 10178 | |||
| 10179 | 16442029 | break; | |
| 10180 | 135319879 | default:; | |
| 10181 | } | ||
| 10182 | |||
| 10183 |
6/6✓ Branch 0 taken 22127499 times.
✓ Branch 1 taken 113192380 times.
✓ Branch 2 taken 305 times.
✓ Branch 3 taken 22127194 times.
✓ Branch 4 taken 305 times.
✓ Branch 5 taken 135319574 times.
|
135320184 | if (field_mysql_type == MYSQL_TYPE_LONGLONG && prebuilt->table->fts && |
| 10184 |
2/4✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 305 times.
✗ Branch 3 not taken.
|
305 | innobase_strcasecmp(field->field_name, FTS_DOC_ID_COL_NAME) == 0) { |
| 10185 |
1/2✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
|
305 | doc_id = (doc_id_t)mach_read_from_n_little_endian(n_ptr, 8); |
| 10186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 305 times.
|
305 | if (doc_id == 0) { |
| 10187 | ✗ | return (DB_FTS_INVALID_DOCID); | |
| 10188 | } | ||
| 10189 | } | ||
| 10190 | |||
| 10191 |
2/2✓ Branch 0 taken 68783151 times.
✓ Branch 1 taken 66536723 times.
|
135319879 | if (field->is_nullable()) { |
| 10192 |
3/4✓ Branch 0 taken 68783150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33515046 times.
✓ Branch 3 taken 35268104 times.
|
68783151 | if (field->is_null_in_record(old_row)) { |
| 10193 | 33515046 | o_len = UNIV_SQL_NULL; | |
| 10194 | } | ||
| 10195 | |||
| 10196 |
3/4✓ Branch 0 taken 68783152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32337755 times.
✓ Branch 3 taken 36445397 times.
|
68783150 | if (field->is_null_in_record(new_row)) { |
| 10197 | 32337755 | n_len = UNIV_SQL_NULL; | |
| 10198 | } | ||
| 10199 | } | ||
| 10200 | |||
| 10201 | #ifdef UNIV_DEBUG | ||
| 10202 | 135319875 | bool online_ord_part = false; | |
| 10203 | #endif | ||
| 10204 | |||
| 10205 |
2/2✓ Branch 0 taken 82320 times.
✓ Branch 1 taken 135237555 times.
|
135319875 | if (is_virtual) { |
| 10206 | /* If the virtual column is not indexed, | ||
| 10207 | we shall ignore it for update */ | ||
| 10208 |
2/2✓ Branch 0 taken 70912 times.
✓ Branch 1 taken 11408 times.
|
82320 | if (!col->ord_part) { |
| 10209 | /* Check whether there is a table-rebuilding | ||
| 10210 | online ALTER TABLE in progress, and this | ||
| 10211 | virtual column could be newly indexed, thus | ||
| 10212 | it will be materialized. Then we will have | ||
| 10213 | to log its update. | ||
| 10214 | Note, we do not support online dropping virtual | ||
| 10215 | column while adding new index, nor with | ||
| 10216 | online alter column order while adding index, | ||
| 10217 | so the virtual column sequence must not change | ||
| 10218 | if it is online operation */ | ||
| 10219 |
5/6✓ Branch 0 taken 70912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 70907 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 70911 times.
|
70917 | if (dict_index_is_online_ddl(clust_index) && |
| 10220 |
3/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
|
5 | row_log_col_is_indexed(clust_index, num_v)) { |
| 10221 | #ifdef UNIV_DEBUG | ||
| 10222 | 1 | online_ord_part = true; | |
| 10223 | #endif | ||
| 10224 | } else { | ||
| 10225 | 70911 | num_v++; | |
| 10226 | 70911 | continue; | |
| 10227 | } | ||
| 10228 | } | ||
| 10229 | |||
| 10230 |
2/2✓ Branch 0 taken 225 times.
✓ Branch 1 taken 11184 times.
|
11409 | if (!uvect->old_vrow) { |
| 10231 | 225 | uvect->old_vrow = | |
| 10232 |
1/2✓ Branch 0 taken 225 times.
✗ Branch 1 not taken.
|
225 | dtuple_create_with_vcol(uvect->heap, 0, prebuilt->table->n_v_cols); |
| 10233 |
2/2✓ Branch 0 taken 397 times.
✓ Branch 1 taken 225 times.
|
622 | for (uint j = 0; j < prebuilt->table->n_v_cols; j++) { |
| 10234 |
1/2✓ Branch 0 taken 397 times.
✗ Branch 1 not taken.
|
397 | dfield_t *field = dtuple_get_nth_v_field(uvect->old_vrow, j); |
| 10235 | /* In case a multi-value field checking read uninitialized value */ | ||
| 10236 |
1/2✓ Branch 0 taken 397 times.
✗ Branch 1 not taken.
|
397 | dfield_get_type(field)->prtype = 0; |
| 10237 |
1/2✓ Branch 0 taken 397 times.
✗ Branch 1 not taken.
|
397 | dfield_set_len(field, UNIV_SQL_NULL); |
| 10238 | } | ||
| 10239 | } | ||
| 10240 | |||
| 10241 |
2/2✓ Branch 0 taken 8189 times.
✓ Branch 1 taken 3220 times.
|
11409 | ulint max_field_len = DICT_MAX_FIELD_LEN_BY_FORMAT(prebuilt->table); |
| 10242 | |||
| 10243 | /* for virtual columns, we only materialize | ||
| 10244 | its index, and index field length would not | ||
| 10245 | exceed max_field_len. So continue if the | ||
| 10246 | first max_field_len bytes are matched up */ | ||
| 10247 |
4/4✓ Branch 0 taken 11344 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 11301 times.
✓ Branch 3 taken 43 times.
|
11409 | if (o_len != UNIV_SQL_NULL && n_len != UNIV_SQL_NULL && |
| 10248 |
3/4✓ Branch 0 taken 5202 times.
✓ Branch 1 taken 6099 times.
✓ Branch 2 taken 5202 times.
✗ Branch 3 not taken.
|
11301 | o_len >= max_field_len && n_len >= max_field_len && |
| 10249 |
2/2✓ Branch 0 taken 1812 times.
✓ Branch 1 taken 3390 times.
|
5202 | memcmp(o_ptr, n_ptr, max_field_len) == 0) { |
| 10250 |
1/2✓ Branch 0 taken 1812 times.
✗ Branch 1 not taken.
|
1812 | dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v); |
| 10251 |
2/4✓ Branch 0 taken 1812 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1812 times.
✗ Branch 3 not taken.
|
1812 | col->copy_type(dfield_get_type(vfield)); |
| 10252 | |||
| 10253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1812 times.
|
1812 | if (is_multi_value) { |
| 10254 | ✗ | innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr, | |
| 10255 | ✗ | static_cast<uint>(old_row - new_row), comp, | |
| 10256 | uvect->per_stmt_heap); | ||
| 10257 | } else { | ||
| 10258 |
1/2✓ Branch 0 taken 1812 times.
✗ Branch 1 not taken.
|
1812 | buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len, |
| 10259 | old_mysql_row_col, col_pack_len, buf); | ||
| 10260 | } | ||
| 10261 | 1812 | num_v++; | |
| 10262 | 1812 | continue; | |
| 10263 | 1812 | } | |
| 10264 | } | ||
| 10265 | |||
| 10266 |
6/6✓ Branch 0 taken 133514021 times.
✓ Branch 1 taken 1733131 times.
✓ Branch 2 taken 101230929 times.
✓ Branch 3 taken 32283092 times.
✓ Branch 4 taken 96864362 times.
✓ Branch 5 taken 4366567 times.
|
135247152 | if (o_len != n_len || (o_len != UNIV_SQL_NULL && o_len != 0 && |
| 10267 |
2/2✓ Branch 0 taken 4993094 times.
✓ Branch 1 taken 91871268 times.
|
96864362 | 0 != memcmp(o_ptr, n_ptr, o_len))) { |
| 10268 | /* The field has changed */ | ||
| 10269 | 6726225 | bool multi_value_calc_by_diff = false; | |
| 10270 | 6726225 | dfield_t old_field, new_field; | |
| 10271 | |||
| 10272 | 6726259 | ufield = uvect->fields + n_changed; | |
| 10273 | |||
| 10274 | 6726259 | const auto old_old_v_val = ufield->old_v_val; | |
| 10275 | |||
| 10276 | UNIV_MEM_INVALID(ufield, sizeof *ufield); | ||
| 10277 | |||
| 10278 | /* Let us use a dummy dfield to make the conversion | ||
| 10279 | from the MySQL column format to the InnoDB format */ | ||
| 10280 | |||
| 10281 | /* If the length of new geometry object is 0, means | ||
| 10282 | this object is invalid geometry object, we need | ||
| 10283 | to block it. */ | ||
| 10284 |
5/8✓ Branch 0 taken 711 times.
✓ Branch 1 taken 6725549 times.
✓ Branch 2 taken 711 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 711 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6726260 times.
|
6726259 | if (DATA_GEOMETRY_MTYPE(col_type) && o_len != 0 && n_len == 0) { |
| 10285 | ✗ | return (DB_CANT_CREATE_GEOMETRY_OBJECT); | |
| 10286 | } | ||
| 10287 | |||
| 10288 |
6/6✓ Branch 0 taken 104 times.
✓ Branch 1 taken 6726156 times.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 77 times.
✓ Branch 5 taken 6726183 times.
|
6726345 | if (is_multi_value && n_len != UNIV_SQL_NULL && |
| 10289 |
3/4✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 8 times.
|
85 | !field->is_null_in_record(old_row)) { |
| 10290 | /* Multi-value field and both old and new are not NULL, | ||
| 10291 | parse the value separately and also calculate the difference */ | ||
| 10292 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
|
77 | ut_ad(is_virtual); |
| 10293 | |||
| 10294 |
2/4✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
|
77 | col->copy_type(dfield_get_type(&old_field)); |
| 10295 |
2/4✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
|
77 | col->copy_type(dfield_get_type(&new_field)); |
| 10296 | |||
| 10297 | 77 | innobase_get_multi_value_and_diff( | |
| 10298 | 77 | prebuilt->m_mysql_table, i, &old_field, &new_field, | |
| 10299 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | static_cast<uint>(old_row - new_row), comp, uvect->per_stmt_heap); |
| 10300 | |||
| 10301 | 77 | multi_value_calc_by_diff = true; | |
| 10302 | } | ||
| 10303 | |||
| 10304 |
2/2✓ Branch 0 taken 6704418 times.
✓ Branch 1 taken 21842 times.
|
6726260 | if (n_len != UNIV_SQL_NULL) { |
| 10305 |
2/4✓ Branch 0 taken 6704414 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6704417 times.
✗ Branch 3 not taken.
|
6704418 | col->copy_type(dfield_get_type(&dfield)); |
| 10306 | |||
| 10307 |
4/4✓ Branch 0 taken 85 times.
✓ Branch 1 taken 6704332 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 77 times.
|
6704417 | if (is_multi_value && !multi_value_calc_by_diff) { |
| 10308 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield, nullptr, |
| 10309 | 0, comp, uvect->per_stmt_heap); | ||
| 10310 | } else { | ||
| 10311 |
1/2✓ Branch 0 taken 6704408 times.
✗ Branch 1 not taken.
|
6704402 | buf = row_mysql_store_col_in_innobase_format( |
| 10312 | &dfield, (byte *)buf, true, new_mysql_row_col, col_pack_len, comp, | ||
| 10313 | 6704409 | field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED, | |
| 10314 | 6704409 | reinterpret_cast<const byte *>(field->zip_dict_data.str), | |
| 10315 | field->zip_dict_data.length, &prebuilt->compress_heap); | ||
| 10316 | } | ||
| 10317 | |||
| 10318 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 6704339 times.
|
6704416 | if (multi_value_calc_by_diff) { |
| 10319 | 77 | dfield_copy(&ufield->new_val, &new_field); | |
| 10320 | } else { | ||
| 10321 | 6704339 | dfield_copy(&ufield->new_val, &dfield); | |
| 10322 | } | ||
| 10323 | } else { | ||
| 10324 |
2/4✓ Branch 0 taken 21840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21840 times.
✗ Branch 3 not taken.
|
21842 | col->copy_type(dfield_get_type(&ufield->new_val)); |
| 10325 |
1/2✓ Branch 0 taken 21841 times.
✗ Branch 1 not taken.
|
21840 | dfield_set_null(&ufield->new_val); |
| 10326 | } | ||
| 10327 | |||
| 10328 | 6726251 | ufield->exp = nullptr; | |
| 10329 | 6726251 | ufield->orig_len = 0; | |
| 10330 | 6726251 | ufield->mysql_field = field; | |
| 10331 | |||
| 10332 |
2/2✓ Branch 0 taken 7683 times.
✓ Branch 1 taken 6718568 times.
|
6726251 | if (is_virtual) { |
| 10333 |
1/2✓ Branch 0 taken 7683 times.
✗ Branch 1 not taken.
|
7683 | dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v); |
| 10334 | 7683 | upd_fld_set_virtual_col(ufield); | |
| 10335 | /* Set ufield->field_no to store the position of virtual column. */ | ||
| 10336 | 7683 | ufield->field_no = num_v; | |
| 10337 | |||
| 10338 |
4/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7682 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7683 times.
|
7683 | ut_ad(col->ord_part || online_ord_part); |
| 10339 |
2/2✓ Branch 0 taken 163 times.
✓ Branch 1 taken 7520 times.
|
7683 | if (old_old_v_val == nullptr) { |
| 10340 | 163 | ufield->old_v_val = static_cast<dfield_t *>( | |
| 10341 |
1/2✓ Branch 0 taken 163 times.
✗ Branch 1 not taken.
|
163 | mem_heap_alloc(uvect->heap, sizeof *ufield->old_v_val)); |
| 10342 | } else { | ||
| 10343 | UNIV_MEM_VALID(ufield, sizeof *ufield); | ||
| 10344 | 7520 | ufield->old_v_val->reset(); | |
| 10345 | } | ||
| 10346 | |||
| 10347 |
3/4✓ Branch 0 taken 7683 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7655 times.
✓ Branch 3 taken 28 times.
|
7683 | if (!field->is_null_in_record(old_row)) { |
| 10348 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 7612 times.
|
7655 | if (n_len == UNIV_SQL_NULL) { |
| 10349 |
2/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
|
43 | col->copy_type(dfield_get_type(&dfield)); |
| 10350 | } | ||
| 10351 | |||
| 10352 |
4/4✓ Branch 0 taken 96 times.
✓ Branch 1 taken 7559 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 77 times.
|
7655 | if (is_multi_value && !multi_value_calc_by_diff) { |
| 10353 | 19 | innobase_get_multi_value(prebuilt->m_mysql_table, i, &dfield, | |
| 10354 | nullptr, | ||
| 10355 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | static_cast<uint>(old_row - new_row), comp, |
| 10356 | uvect->per_stmt_heap); | ||
| 10357 | } else { | ||
| 10358 |
1/2✓ Branch 0 taken 7636 times.
✗ Branch 1 not taken.
|
7636 | buf = row_mysql_store_col_in_innobase_format( |
| 10359 | &dfield, (byte *)buf, true, old_mysql_row_col, col_pack_len, | ||
| 10360 | 7636 | comp, field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED, | |
| 10361 | 7636 | reinterpret_cast<const byte *>(field->zip_dict_data.str), | |
| 10362 | field->zip_dict_data.length, &prebuilt->compress_heap); | ||
| 10363 | } | ||
| 10364 | |||
| 10365 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 7578 times.
|
7655 | if (multi_value_calc_by_diff) { |
| 10366 | 77 | dfield_copy(ufield->old_v_val, &old_field); | |
| 10367 | 77 | dfield_copy(vfield, &old_field); | |
| 10368 | } else { | ||
| 10369 | 7578 | dfield_copy(ufield->old_v_val, &dfield); | |
| 10370 | 7578 | dfield_copy(vfield, &dfield); | |
| 10371 | } | ||
| 10372 | } else { | ||
| 10373 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | col->copy_type(dfield_get_type(ufield->old_v_val)); |
| 10374 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | dfield_set_null(ufield->old_v_val); |
| 10375 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | dfield_set_null(vfield); |
| 10376 | } | ||
| 10377 | 7683 | num_v++; | |
| 10378 | } else { | ||
| 10379 | /* Set ufield->field_no to store the position of column in | ||
| 10380 | clustered index. */ | ||
| 10381 | 13437136 | ufield->field_no = dict_col_get_clust_pos( | |
| 10382 |
1/2✓ Branch 0 taken 6718568 times.
✗ Branch 1 not taken.
|
6718568 | &prebuilt->table->cols[i - num_v], clust_index); |
| 10383 | #ifdef UNIV_DEBUG | ||
| 10384 |
2/2✓ Branch 0 taken 396 times.
✓ Branch 1 taken 6718176 times.
|
6718568 | if (clust_index->has_row_versions()) { |
| 10385 | 396 | dict_col_t *col = &prebuilt->table->cols[i - num_v]; | |
| 10386 | 396 | ufield->field_phy_pos = col->get_col_phy_pos(); | |
| 10387 | } | ||
| 10388 | #endif | ||
| 10389 | 6718572 | ufield->old_v_val = nullptr; | |
| 10390 | } | ||
| 10391 | 6726255 | n_changed++; | |
| 10392 | |||
| 10393 | /* If an FTS indexed column was changed by this | ||
| 10394 | UPDATE then we need to inform the FTS sub-system. | ||
| 10395 | |||
| 10396 | NOTE: Currently we re-index all FTS indexed columns | ||
| 10397 | even if only a subset of the FTS indexed columns | ||
| 10398 | have been updated. That is the reason we are | ||
| 10399 | checking only once here. Later we will need to | ||
| 10400 | note which columns have been updated and do | ||
| 10401 | selective processing. */ | ||
| 10402 |
3/4✓ Branch 0 taken 1998 times.
✓ Branch 1 taken 6724257 times.
✓ Branch 2 taken 1998 times.
✗ Branch 3 not taken.
|
6726255 | if (prebuilt->table->fts != nullptr && !is_virtual) { |
| 10403 | ulint offset; | ||
| 10404 | dict_table_t *innodb_table; | ||
| 10405 | |||
| 10406 | 1998 | innodb_table = prebuilt->table; | |
| 10407 | |||
| 10408 |
2/2✓ Branch 0 taken 1684 times.
✓ Branch 1 taken 314 times.
|
1998 | if (!changes_fts_column) { |
| 10409 |
1/2✓ Branch 0 taken 1684 times.
✗ Branch 1 not taken.
|
1684 | offset = row_upd_changes_fts_column(innodb_table, ufield); |
| 10410 | |||
| 10411 |
2/2✓ Branch 0 taken 1367 times.
✓ Branch 1 taken 317 times.
|
1684 | if (offset != ULINT_UNDEFINED) { |
| 10412 | 1367 | changes_fts_column = true; | |
| 10413 | } | ||
| 10414 | } | ||
| 10415 | |||
| 10416 |
2/2✓ Branch 0 taken 1393 times.
✓ Branch 1 taken 605 times.
|
1998 | if (!changes_fts_doc_col) { |
| 10417 |
1/2✓ Branch 0 taken 1393 times.
✗ Branch 1 not taken.
|
1393 | changes_fts_doc_col = row_upd_changes_doc_id(innodb_table, ufield); |
| 10418 | } | ||
| 10419 | } | ||
| 10420 |
2/2✓ Branch 0 taken 1914 times.
✓ Branch 1 taken 128519013 times.
|
135247182 | } else if (is_virtual) { |
| 10421 |
1/2✓ Branch 0 taken 1914 times.
✗ Branch 1 not taken.
|
1914 | dfield_t *vfield = dtuple_get_nth_v_field(uvect->old_vrow, num_v); |
| 10422 |
2/4✓ Branch 0 taken 1914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1914 times.
✗ Branch 3 not taken.
|
1914 | col->copy_type(dfield_get_type(vfield)); |
| 10423 | |||
| 10424 |
2/2✓ Branch 0 taken 89 times.
✓ Branch 1 taken 1825 times.
|
1914 | if (is_multi_value) { |
| 10425 | 89 | innobase_get_multi_value(prebuilt->m_mysql_table, i, vfield, nullptr, | |
| 10426 |
1/2✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
|
89 | static_cast<uint>(old_row - new_row), comp, |
| 10427 | uvect->per_stmt_heap); | ||
| 10428 | } else { | ||
| 10429 |
1/2✓ Branch 0 taken 1825 times.
✗ Branch 1 not taken.
|
1825 | buf = innodb_fill_old_vcol_val(prebuilt, vfield, o_len, |
| 10430 | old_mysql_row_col, col_pack_len, buf); | ||
| 10431 | } | ||
| 10432 | |||
| 10433 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 1914 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1914 times.
|
1914 | ut_ad(col->ord_part || online_ord_part); |
| 10434 | 1914 | num_v++; | |
| 10435 | } | ||
| 10436 | } | ||
| 10437 | |||
| 10438 | /* If the update changes a column with an FTS index on it, we | ||
| 10439 | then add an update column node with a new document id to the | ||
| 10440 | other changes. We piggy back our changes on the normal UPDATE | ||
| 10441 | to reduce processing and IO overhead. */ | ||
| 10442 |
2/2✓ Branch 0 taken 11736601 times.
✓ Branch 1 taken 1439 times.
|
11738040 | if (!prebuilt->table->fts) { |
| 10443 | 11736601 | trx->fts_next_doc_id = 0; | |
| 10444 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1426 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
1439 | } else if (changes_fts_column || changes_fts_doc_col) { |
| 10445 | 1426 | dict_table_t *innodb_table = prebuilt->table; | |
| 10446 | |||
| 10447 | 1426 | ufield = uvect->fields + n_changed; | |
| 10448 | |||
| 10449 |
2/2✓ Branch 0 taken 305 times.
✓ Branch 1 taken 1062 times.
|
1426 | if (!DICT_TF2_FLAG_IS_SET(innodb_table, DICT_TF2_FTS_HAS_DOC_ID)) { |
| 10450 | /* If Doc ID is managed by user, and if any | ||
| 10451 | FTS indexed column has been updated, its corresponding | ||
| 10452 | Doc ID must also be updated. Otherwise, return | ||
| 10453 | error */ | ||
| 10454 |
3/4✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 304 times.
|
305 | if (changes_fts_column && !changes_fts_doc_col) { |
| 10455 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | ib::warn(ER_IB_MSG_559) << "A new Doc ID must be supplied" |
| 10456 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | " while updating FTS indexed columns."; |
| 10457 | 1 | return (DB_FTS_INVALID_DOCID); | |
| 10458 | } | ||
| 10459 | |||
| 10460 | /* Doc ID must monotonically increase */ | ||
| 10461 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 304 times.
|
304 | ut_ad(innodb_table->fts->cache); |
| 10462 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 303 times.
|
304 | if (doc_id < prebuilt->table->fts->cache->next_doc_id) { |
| 10463 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ib::warn(ER_IB_MSG_560) << "FTS Doc ID must be larger than " |
| 10464 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | << innodb_table->fts->cache->next_doc_id - 1 |
| 10465 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | << " for table " << innodb_table->name; |
| 10466 | |||
| 10467 | 1 | return (DB_FTS_INVALID_DOCID); | |
| 10468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | } else if ((doc_id - prebuilt->table->fts->cache->next_doc_id) >= |
| 10469 | FTS_DOC_ID_MAX_STEP) { | ||
| 10470 | ✗ | ib::warn(ER_IB_MSG_561) | |
| 10471 | ✗ | << "Doc ID " << doc_id | |
| 10472 | << " is too" | ||
| 10473 | " big. Its difference with largest" | ||
| 10474 | ✗ | " Doc ID used " | |
| 10475 | ✗ | << prebuilt->table->fts->cache->next_doc_id - 1 | |
| 10476 | ✗ | << " cannot exceed or equal to " << FTS_DOC_ID_MAX_STEP; | |
| 10477 | } | ||
| 10478 | |||
| 10479 | 303 | trx->fts_next_doc_id = doc_id; | |
| 10480 | } else { | ||
| 10481 | /* If the Doc ID is a hidden column, it can't be | ||
| 10482 | changed by user */ | ||
| 10483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1062 times.
|
1062 | ut_ad(!changes_fts_doc_col); |
| 10484 | |||
| 10485 | /* Doc ID column is hidden, a new Doc ID will be | ||
| 10486 | generated by following fts_update_doc_id() call */ | ||
| 10487 | 1062 | trx->fts_next_doc_id = 0; | |
| 10488 | } | ||
| 10489 | |||
| 10490 |
1/2✓ Branch 0 taken 1365 times.
✗ Branch 1 not taken.
|
1365 | fts_update_doc_id(innodb_table, ufield, &trx->fts_next_doc_id); |
| 10491 | |||
| 10492 | 1365 | ++n_changed; | |
| 10493 | 1365 | } else { | |
| 10494 | /* We have a Doc ID column, but none of FTS indexed | ||
| 10495 | columns are touched, nor the Doc ID column, so set | ||
| 10496 | fts_next_doc_id to UINT64_UNDEFINED, which means do not | ||
| 10497 | update the Doc ID column */ | ||
| 10498 | 13 | trx->fts_next_doc_id = UINT64_UNDEFINED; | |
| 10499 | } | ||
| 10500 | |||
| 10501 | 11737979 | uvect->n_fields = n_changed; | |
| 10502 | 11737979 | uvect->info_bits = 0; | |
| 10503 | |||
| 10504 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11737973 times.
|
11737979 | ut_a(buf <= (byte *)original_upd_buff + buff_len); |
| 10505 | |||
| 10506 |
2/4✓ Branch 0 taken 11737978 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11737977 times.
|
11737973 | ut_ad(uvect->validate()); |
| 10507 | 11737977 | return (DB_SUCCESS); | |
| 10508 | } | ||
| 10509 | |||
| 10510 | /** | ||
| 10511 | Updates a row given as a parameter to a new value. Note that we are given | ||
| 10512 | whole rows, not just the fields which are updated: this incurs some | ||
| 10513 | overhead for CPU when we check which fields are actually updated. | ||
| 10514 | TODO: currently InnoDB does not prevent the 'Halloween problem': | ||
| 10515 | in a searched update a single row can get updated several times | ||
| 10516 | if its index columns are updated! | ||
| 10517 | @param[in] old_row Old row contents in MySQL format | ||
| 10518 | @param[out] new_row Updated row contents in MySQL format | ||
| 10519 | @return error number or 0 */ | ||
| 10520 | |||
| 10521 | 11737980 | int ha_innobase::update_row(const uchar *old_row, uchar *new_row) { | |
| 10522 | int err; | ||
| 10523 | |||
| 10524 | dberr_t error; | ||
| 10525 |
1/2✓ Branch 0 taken 11737986 times.
✗ Branch 1 not taken.
|
11737980 | trx_t *trx = thd_to_trx(m_user_thd); |
| 10526 | 11737986 | uint64_t new_counter = 0; | |
| 10527 | |||
| 10528 |
1/2✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
|
11737986 | DBUG_TRACE; |
| 10529 | |||
| 10530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11737985 times.
|
11737981 | ut_a(m_prebuilt->trx == trx); |
| 10531 | |||
| 10532 |
7/8✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11737976 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 11737980 times.
|
11737985 | if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) { |
| 10533 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 10534 | 5 | return HA_ERR_TABLE_READONLY; | |
| 10535 |
2/4✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11737981 times.
|
11737980 | } else if (!trx_is_started(trx)) { |
| 10536 | ✗ | ++trx->will_lock; | |
| 10537 | } | ||
| 10538 | |||
| 10539 |
2/2✓ Branch 0 taken 238363 times.
✓ Branch 1 taken 11499618 times.
|
11737981 | if (m_upd_buf == nullptr) { |
| 10540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 238363 times.
|
238363 | ut_ad(m_upd_buf_size == 0); |
| 10541 | |||
| 10542 | /* Create a buffer for packing the fields of a record. Why | ||
| 10543 | table->reclength did not work here? Obviously, because char | ||
| 10544 | fields when packed actually became 1 byte longer, when we also | ||
| 10545 | stored the string length as the first byte. */ | ||
| 10546 | |||
| 10547 | 238363 | m_upd_buf_size = | |
| 10548 | 238363 | table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3; | |
| 10549 | |||
| 10550 | 238363 | m_upd_buf = reinterpret_cast<uchar *>( | |
| 10551 |
1/2✓ Branch 0 taken 238363 times.
✗ Branch 1 not taken.
|
238363 | my_malloc(PSI_INSTRUMENT_ME, m_upd_buf_size, MYF(MY_WME))); |
| 10552 | |||
| 10553 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 238363 times.
|
238363 | if (m_upd_buf == nullptr) { |
| 10554 | ✗ | m_upd_buf_size = 0; | |
| 10555 | ✗ | return HA_ERR_OUT_OF_MEM; | |
| 10556 | } | ||
| 10557 | } | ||
| 10558 | |||
| 10559 |
1/2✓ Branch 0 taken 11737981 times.
✗ Branch 1 not taken.
|
11737981 | ha_statistic_increment(&System_status_var::ha_update_count); |
| 10560 | |||
| 10561 |
5/10✓ Branch 0 taken 11654690 times.
✓ Branch 1 taken 83291 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11654690 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11737981 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 11737981 times.
|
11737981 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 10562 | m_share->ib_table->is_corrupt)) | ||
| 10563 | ✗ | return HA_ERR_CRASHED; | |
| 10564 | |||
| 10565 | upd_t *uvect; | ||
| 10566 | |||
| 10567 |
2/2✓ Branch 0 taken 11520845 times.
✓ Branch 1 taken 217136 times.
|
11737981 | if (m_prebuilt->upd_node) { |
| 10568 | 11520845 | uvect = m_prebuilt->upd_node->update; | |
| 10569 | } else { | ||
| 10570 |
1/2✓ Branch 0 taken 217137 times.
✗ Branch 1 not taken.
|
217136 | uvect = row_get_prebuilt_update_vector(m_prebuilt); |
| 10571 | } | ||
| 10572 | |||
| 10573 | 11737982 | uvect->table = m_prebuilt->table; | |
| 10574 | 11737982 | uvect->mysql_table = table; | |
| 10575 | |||
| 10576 | /* Build an update vector from the modified fields in the rows | ||
| 10577 | (uses m_upd_buf of the handle) */ | ||
| 10578 | |||
| 10579 |
1/2✓ Branch 0 taken 11737979 times.
✗ Branch 1 not taken.
|
11737982 | error = calc_row_difference(uvect, old_row, new_row, table, m_upd_buf, |
| 10580 | m_upd_buf_size, m_prebuilt, m_user_thd); | ||
| 10581 | |||
| 10582 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11737977 times.
|
11737979 | if (error != DB_SUCCESS) { |
| 10583 | 2 | goto func_exit; | |
| 10584 | } | ||
| 10585 | |||
| 10586 |
6/10✓ Branch 0 taken 11737978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11721563 times.
✓ Branch 3 taken 16415 times.
✓ Branch 4 taken 11721557 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11721557 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11737972 times.
|
11737977 | if (!m_prebuilt->table->is_intrinsic() && TrxInInnoDB::is_aborted(trx)) { |
| 10587 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 10588 | |||
| 10589 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 10590 | } | ||
| 10591 | |||
| 10592 | /* This is not a delete */ | ||
| 10593 | 11737972 | m_prebuilt->upd_node->is_delete = false; | |
| 10594 | |||
| 10595 |
1/2✓ Branch 0 taken 11737975 times.
✗ Branch 1 not taken.
|
11737972 | error = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 10596 | |||
| 10597 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11737975 times.
|
11737975 | if (error != DB_SUCCESS) { |
| 10598 | ✗ | goto func_exit; | |
| 10599 | } | ||
| 10600 | |||
| 10601 |
1/2✓ Branch 0 taken 11737965 times.
✗ Branch 1 not taken.
|
11737975 | error = row_update_for_mysql((byte *)old_row, m_prebuilt); |
| 10602 | |||
| 10603 |
2/2✓ Branch 0 taken 6491290 times.
✓ Branch 1 taken 5246677 times.
|
11737965 | if (dict_table_has_autoinc_col(m_prebuilt->table)) { |
| 10604 | 6491291 | new_counter = row_upd_get_new_autoinc_counter( | |
| 10605 |
1/2✓ Branch 0 taken 6491291 times.
✗ Branch 1 not taken.
|
6491290 | uvect, m_prebuilt->table->autoinc_field_no); |
| 10606 | } else { | ||
| 10607 | 5246677 | new_counter = 0; | |
| 10608 | } | ||
| 10609 | |||
| 10610 | /* We should handle the case if the AUTOINC counter has been | ||
| 10611 | updated, we want to update the counter accordingly. | ||
| 10612 | |||
| 10613 | We need to do some special AUTOINC handling for the following case: | ||
| 10614 | |||
| 10615 | INSERT INTO t (c1,c2) VALUES(x,y) ON DUPLICATE KEY UPDATE ... | ||
| 10616 | |||
| 10617 | We need to use the AUTOINC counter that was actually used by | ||
| 10618 | MySQL in the UPDATE statement, which can be different from the | ||
| 10619 | value used in the INSERT statement. */ | ||
| 10620 | |||
| 10621 |
6/6✓ Branch 0 taken 11737422 times.
✓ Branch 1 taken 546 times.
✓ Branch 2 taken 11736639 times.
✓ Branch 3 taken 783 times.
✓ Branch 4 taken 843 times.
✓ Branch 5 taken 11737125 times.
|
23474607 | if (error == DB_SUCCESS && |
| 10622 | 11736639 | (new_counter != 0 || | |
| 10623 |
3/4✓ Branch 0 taken 75 times.
✓ Branch 1 taken 11736564 times.
✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
|
11736639 | (table->next_number_field && new_row == table->record[0] && |
| 10624 |
4/6✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
|
135 | thd_sql_command(m_user_thd) == SQLCOM_INSERT && |
| 10625 | 60 | m_prebuilt->allow_duplicates()))) { | |
| 10626 | ulonglong auto_inc; | ||
| 10627 | ulonglong col_max_value; | ||
| 10628 | |||
| 10629 |
2/2✓ Branch 0 taken 783 times.
✓ Branch 1 taken 60 times.
|
843 | if (new_counter != 0) { |
| 10630 | 783 | auto_inc = new_counter; | |
| 10631 | } else { | ||
| 10632 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
|
60 | ut_ad(table->next_number_field != nullptr); |
| 10633 |
1/2✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
|
60 | auto_inc = table->next_number_field->val_int(); |
| 10634 | } | ||
| 10635 | |||
| 10636 | /* We need the upper limit of the col type to check for | ||
| 10637 | whether we update the table autoinc counter or not. */ | ||
| 10638 |
1/2✓ Branch 0 taken 843 times.
✗ Branch 1 not taken.
|
843 | col_max_value = table->found_next_number_field->get_max_int_value(); |
| 10639 | |||
| 10640 |
3/4✓ Branch 0 taken 843 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 840 times.
✓ Branch 3 taken 3 times.
|
843 | if (auto_inc <= col_max_value && auto_inc != 0) { |
| 10641 | ulonglong offset; | ||
| 10642 | ulonglong increment; | ||
| 10643 | |||
| 10644 | 840 | offset = m_prebuilt->autoinc_offset; | |
| 10645 | 840 | increment = m_prebuilt->autoinc_increment; | |
| 10646 | |||
| 10647 | auto_inc = | ||
| 10648 |
1/2✓ Branch 0 taken 840 times.
✗ Branch 1 not taken.
|
840 | innobase_next_autoinc(auto_inc, 1, increment, offset, col_max_value); |
| 10649 | |||
| 10650 |
1/2✓ Branch 0 taken 840 times.
✗ Branch 1 not taken.
|
840 | error = innobase_set_max_autoinc(auto_inc); |
| 10651 | } | ||
| 10652 | } | ||
| 10653 | |||
| 10654 |
1/2✓ Branch 0 taken 11737967 times.
✗ Branch 1 not taken.
|
11737968 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 10655 | |||
| 10656 | 11737969 | func_exit: | |
| 10657 | |||
| 10658 | err = | ||
| 10659 |
1/2✓ Branch 0 taken 11737969 times.
✗ Branch 1 not taken.
|
11737969 | convert_error_code_to_mysql(error, m_prebuilt->table->flags, m_user_thd); |
| 10660 | |||
| 10661 | /* If success and no columns were updated. */ | ||
| 10662 |
4/4✓ Branch 0 taken 11737421 times.
✓ Branch 1 taken 548 times.
✓ Branch 2 taken 7075507 times.
✓ Branch 3 taken 4661914 times.
|
11737969 | if (err == 0 && uvect->n_fields == 0) { |
| 10663 | /* This is the same as success, but instructs | ||
| 10664 | MySQL that the row is not really updated and it | ||
| 10665 | should not increase the count of updated rows. | ||
| 10666 | This is fix for http://bugs.mysql.com/29157 */ | ||
| 10667 | 7075507 | err = HA_ERR_RECORD_IS_THE_SAME; | |
| 10668 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4662460 times.
|
4662462 | } else if (err == HA_FTS_INVALID_DOCID) { |
| 10669 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(HA_FTS_INVALID_DOCID, MYF(0)); |
| 10670 | } | ||
| 10671 | |||
| 10672 | /* Tell InnoDB server that there might be work for | ||
| 10673 | utility threads: */ | ||
| 10674 | |||
| 10675 |
1/2✓ Branch 0 taken 11737965 times.
✗ Branch 1 not taken.
|
11737969 | innobase_active_small(); |
| 10676 | |||
| 10677 |
5/10✓ Branch 0 taken 11654678 times.
✓ Branch 1 taken 83287 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11654678 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11737965 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 11737965 times.
|
11737965 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 10678 | m_share->ib_table->is_corrupt)) | ||
| 10679 | ✗ | return HA_ERR_CRASHED; | |
| 10680 | |||
| 10681 | 11737965 | return err; | |
| 10682 | 11737970 | } | |
| 10683 | |||
| 10684 | /** Deletes a row given as the parameter. | ||
| 10685 | @return error number or 0 */ | ||
| 10686 | |||
| 10687 | 8178464 | int ha_innobase::delete_row( | |
| 10688 | const uchar *record) /*!< in: a row in MySQL format */ | ||
| 10689 | { | ||
| 10690 | dberr_t error; | ||
| 10691 |
1/2✓ Branch 0 taken 8178465 times.
✗ Branch 1 not taken.
|
8178464 | trx_t *trx = thd_to_trx(m_user_thd); |
| 10692 |
1/2✓ Branch 0 taken 8178464 times.
✗ Branch 1 not taken.
|
8178465 | TrxInInnoDB trx_in_innodb(trx); |
| 10693 | |||
| 10694 |
1/2✓ Branch 0 taken 8178464 times.
✗ Branch 1 not taken.
|
8178464 | DBUG_TRACE; |
| 10695 | |||
| 10696 |
5/10✓ Branch 0 taken 8178464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8178464 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8178465 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8178465 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8178465 times.
|
8178464 | if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) { |
| 10697 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 10698 | |||
| 10699 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 10700 | } | ||
| 10701 | |||
| 10702 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8178464 times.
|
8178465 | ut_a(m_prebuilt->trx == trx); |
| 10703 | |||
| 10704 |
6/8✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8178459 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 8178459 times.
|
8178464 | if (high_level_read_only && !m_prebuilt->table->is_intrinsic()) { |
| 10705 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 10706 | 5 | return HA_ERR_TABLE_READONLY; | |
| 10707 |
2/4✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8178460 times.
|
8178459 | } else if (!trx_is_started(trx)) { |
| 10708 | ✗ | ++trx->will_lock; | |
| 10709 | } | ||
| 10710 | |||
| 10711 |
1/2✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
|
8178460 | ha_statistic_increment(&System_status_var::ha_delete_count); |
| 10712 | |||
| 10713 |
5/10✓ Branch 0 taken 8147671 times.
✓ Branch 1 taken 30789 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8147671 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8178460 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8178460 times.
|
8178460 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 10714 | m_share->ib_table->is_corrupt)) | ||
| 10715 | ✗ | return HA_ERR_CRASHED; | |
| 10716 | |||
| 10717 |
2/2✓ Branch 0 taken 159902 times.
✓ Branch 1 taken 8018558 times.
|
8178460 | if (!m_prebuilt->upd_node) { |
| 10718 |
1/2✓ Branch 0 taken 159902 times.
✗ Branch 1 not taken.
|
159902 | row_get_prebuilt_update_vector(m_prebuilt); |
| 10719 | } | ||
| 10720 | |||
| 10721 | /* This is a delete */ | ||
| 10722 | |||
| 10723 | 8178460 | m_prebuilt->upd_node->is_delete = true; | |
| 10724 | |||
| 10725 |
1/2✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
|
8178460 | error = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 10726 | |||
| 10727 |
1/2✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
|
8178460 | if (error == DB_SUCCESS) { |
| 10728 |
1/2✓ Branch 0 taken 8178459 times.
✗ Branch 1 not taken.
|
8178460 | error = row_update_for_mysql((byte *)record, m_prebuilt); |
| 10729 |
1/2✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
|
8178459 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 10730 | } | ||
| 10731 | |||
| 10732 | /* Tell the InnoDB server that there might be work for | ||
| 10733 | utility threads: */ | ||
| 10734 | |||
| 10735 |
1/2✓ Branch 0 taken 8178460 times.
✗ Branch 1 not taken.
|
8178460 | innobase_active_small(); |
| 10736 | |||
| 10737 |
5/10✓ Branch 0 taken 8147671 times.
✓ Branch 1 taken 30789 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8147671 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8178460 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8178460 times.
|
8178460 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 10738 | m_share->ib_table->is_corrupt)) | ||
| 10739 | ✗ | return HA_ERR_CRASHED; | |
| 10740 | |||
| 10741 |
1/2✓ Branch 0 taken 8178459 times.
✗ Branch 1 not taken.
|
8178460 | return convert_error_code_to_mysql(error, m_prebuilt->table->flags, |
| 10742 | 8178459 | m_user_thd); | |
| 10743 | 8178464 | } | |
| 10744 | |||
| 10745 | /** Delete all rows from the table. | ||
| 10746 | @retval HA_ERR_WRONG_COMMAND if the table is transactional | ||
| 10747 | @retval 0 on success */ | ||
| 10748 | 121856 | int ha_innobase::delete_all_rows() { | |
| 10749 |
1/2✓ Branch 0 taken 121856 times.
✗ Branch 1 not taken.
|
121856 | DBUG_TRACE; |
| 10750 | |||
| 10751 |
3/4✓ Branch 0 taken 121856 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 685 times.
✓ Branch 3 taken 121171 times.
|
121856 | if (!m_prebuilt->table->is_intrinsic()) { |
| 10752 | /* Transactional tables should use truncate(). */ | ||
| 10753 | 685 | return HA_ERR_WRONG_COMMAND; | |
| 10754 | } | ||
| 10755 | |||
| 10756 |
1/2✓ Branch 0 taken 121171 times.
✗ Branch 1 not taken.
|
121171 | row_delete_all_rows(m_prebuilt->table); |
| 10757 | |||
| 10758 |
1/2✓ Branch 0 taken 121171 times.
✗ Branch 1 not taken.
|
121171 | dict_stats_update(m_prebuilt->table, DICT_STATS_EMPTY_TABLE); |
| 10759 | |||
| 10760 | 121171 | return 0; | |
| 10761 | 121856 | } | |
| 10762 | |||
| 10763 | /** Removes a new lock set on a row, if it was not read optimistically. This can | ||
| 10764 | be called after a row has been read in the processing of an UPDATE or a DELETE | ||
| 10765 | query, when the record doesn't match the WHERE condition. */ | ||
| 10766 | |||
| 10767 | 39157926 | void ha_innobase::unlock_row(void) { | |
| 10768 |
1/2✓ Branch 0 taken 39157926 times.
✗ Branch 1 not taken.
|
39157926 | DBUG_TRACE; |
| 10769 | |||
| 10770 | /* Consistent read does not take any locks, thus there is | ||
| 10771 | nothing to unlock. There is no locking for intrinsic table. */ | ||
| 10772 | |||
| 10773 |
4/4✓ Branch 0 taken 13198048 times.
✓ Branch 1 taken 25959878 times.
✓ Branch 2 taken 25959878 times.
✓ Branch 3 taken 13198048 times.
|
52355974 | if (m_prebuilt->select_lock_type == LOCK_NONE || |
| 10774 |
2/4✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
|
13198048 | m_prebuilt->table->is_intrinsic()) { |
| 10775 | 25959878 | return; | |
| 10776 | } | ||
| 10777 | |||
| 10778 |
1/2✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
|
13198048 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 10779 | |||
| 10780 |
2/4✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
|
13198048 | if (trx_in_innodb.is_aborted()) { |
| 10781 | ✗ | return; | |
| 10782 | } | ||
| 10783 | |||
| 10784 |
2/4✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
|
13198048 | ut_ad(!m_prebuilt->table->is_intrinsic()); |
| 10785 | |||
| 10786 | /* Ideally, this assert must be in the beginning of the function. | ||
| 10787 | But there are some calls to this function from the SQL layer when the | ||
| 10788 | transaction is in state TRX_STATE_NOT_STARTED. The check on | ||
| 10789 | m_prebuilt->select_lock_type above gets around this issue. */ | ||
| 10790 | |||
| 10791 |
3/10✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13198048 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13198048 times.
|
13198048 | ut_ad(trx_state_eq(m_prebuilt->trx, TRX_STATE_ACTIVE) || |
| 10792 | trx_state_eq(m_prebuilt->trx, TRX_STATE_FORCED_ROLLBACK)); | ||
| 10793 | |||
| 10794 | /* The purpose of unlock_row() is to release locks held on non-matching row | ||
| 10795 | found during most recent row_search_mvcc() call. | ||
| 10796 | In higher isolation levels row_try_unlock() is a no-op, as we only set the | ||
| 10797 | m_prebuilt->new_rec_lock[i] when trx->releases_non_matching_rows(). | ||
| 10798 | In lower isolation levels row_try_unlock() will remove the record locks which | ||
| 10799 | were newly created during the most recent row_search_mvcc() (the record locks | ||
| 10800 | which were merely reused, are not released as they are still needed). | ||
| 10801 | @see handler::was_semi_consistent_read() for great explanation of what | ||
| 10802 | semi-consistent read mode is all about and why we don't call row_try_unlock() | ||
| 10803 | in case of ROW_READ_DID_SEMI_CONSISTENT, and reset the flag instead; in short | ||
| 10804 | a successful semi-consistent read means we didn't acquire any lock, so don't | ||
| 10805 | need to unlock anything if the row doesn't match the query. */ | ||
| 10806 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 13198009 times.
|
13198048 | if (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT) { |
| 10807 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | ut_ad(m_prebuilt->new_rec_locks_count() == 0); |
| 10808 | 39 | m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT; | |
| 10809 | } | ||
| 10810 |
1/2✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
|
13198048 | m_prebuilt->try_unlock(false); |
| 10811 |
3/4✓ Branch 0 taken 13198048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13198048 times.
✓ Branch 3 taken 25959878 times.
|
39157926 | } |
| 10812 | |||
| 10813 | /* See handler.h and row0mysql.h for docs on this function. */ | ||
| 10814 | |||
| 10815 | 2947353 | bool ha_innobase::was_semi_consistent_read(void) { | |
| 10816 | 2947353 | return (m_prebuilt->row_read_type == ROW_READ_DID_SEMI_CONSISTENT); | |
| 10817 | } | ||
| 10818 | |||
| 10819 | /* See handler.h and row0mysql.h for docs on this function. */ | ||
| 10820 | |||
| 10821 | 418634 | void ha_innobase::try_semi_consistent_read(bool yes) { | |
| 10822 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 418683 times.
|
418634 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 10823 | |||
| 10824 |
6/6✓ Branch 0 taken 204255 times.
✓ Branch 1 taken 214428 times.
✓ Branch 2 taken 537 times.
✓ Branch 3 taken 203715 times.
✓ Branch 4 taken 537 times.
✓ Branch 5 taken 418143 times.
|
418683 | if (yes && m_prebuilt->trx->allow_semi_consistent()) { |
| 10825 | 537 | m_prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT; | |
| 10826 | |||
| 10827 | } else { | ||
| 10828 | 418143 | m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS; | |
| 10829 | } | ||
| 10830 | 418680 | } | |
| 10831 | |||
| 10832 | /** Initializes a handle to use an index. | ||
| 10833 | @return 0 or error number */ | ||
| 10834 | 104094134 | int ha_innobase::index_init(uint keynr, /*!< in: key (index) number */ | |
| 10835 | bool) /*!< in: 1 if result | ||
| 10836 | MUST be sorted | ||
| 10837 | according to index */ | ||
| 10838 | { | ||
| 10839 |
1/2✓ Branch 0 taken 104094429 times.
✗ Branch 1 not taken.
|
104094134 | DBUG_TRACE; |
| 10840 | |||
| 10841 |
1/2✓ Branch 0 taken 104094416 times.
✗ Branch 1 not taken.
|
208188891 | return change_active_index(keynr); |
| 10842 | 104094416 | } | |
| 10843 | |||
| 10844 | /** Currently does nothing. | ||
| 10845 | @return 0 */ | ||
| 10846 | |||
| 10847 | 106216059 | int ha_innobase::index_end(void) { | |
| 10848 |
1/2✓ Branch 0 taken 106216089 times.
✗ Branch 1 not taken.
|
106216059 | DBUG_TRACE; |
| 10849 | |||
| 10850 |
2/2✓ Branch 0 taken 142748 times.
✓ Branch 1 taken 106073341 times.
|
106216089 | if (m_prebuilt->index->last_sel_cur) { |
| 10851 |
1/2✓ Branch 0 taken 142748 times.
✗ Branch 1 not taken.
|
142748 | m_prebuilt->index->last_sel_cur->release(); |
| 10852 | } | ||
| 10853 | |||
| 10854 | 106216089 | active_index = MAX_KEY; | |
| 10855 | |||
| 10856 | 106216089 | in_range_check_pushed_down = false; | |
| 10857 | |||
| 10858 |
1/2✓ Branch 0 taken 106216083 times.
✗ Branch 1 not taken.
|
106216089 | m_ds_mrr.dsmrr_close(); |
| 10859 | |||
| 10860 | 106216087 | return 0; | |
| 10861 | 106216083 | } | |
| 10862 | |||
| 10863 | /** Converts a search mode flag understood by MySQL to a flag understood | ||
| 10864 | by InnoDB. */ | ||
| 10865 | 72351652 | page_cur_mode_t convert_search_mode_to_innobase(ha_rkey_function find_flag) { | |
| 10866 |
9/12✓ Branch 0 taken 68059845 times.
✓ Branch 1 taken 4269290 times.
✓ Branch 2 taken 15185 times.
✓ Branch 3 taken 6703 times.
✓ Branch 4 taken 192 times.
✓ Branch 5 taken 271 times.
✓ Branch 6 taken 70 times.
✓ Branch 7 taken 41 times.
✓ Branch 8 taken 65 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
72351652 | switch (find_flag) { |
| 10867 | 68059845 | case HA_READ_KEY_EXACT: | |
| 10868 | /* this does not require the index to be UNIQUE */ | ||
| 10869 | case HA_READ_KEY_OR_NEXT: | ||
| 10870 | 68059845 | return (PAGE_CUR_GE); | |
| 10871 | 4269290 | case HA_READ_AFTER_KEY: | |
| 10872 | 4269290 | return (PAGE_CUR_G); | |
| 10873 | 15185 | case HA_READ_BEFORE_KEY: | |
| 10874 | 15185 | return (PAGE_CUR_L); | |
| 10875 | 6703 | case HA_READ_KEY_OR_PREV: | |
| 10876 | case HA_READ_PREFIX_LAST: | ||
| 10877 | case HA_READ_PREFIX_LAST_OR_PREV: | ||
| 10878 | 6703 | return (PAGE_CUR_LE); | |
| 10879 | 192 | case HA_READ_MBR_CONTAIN: | |
| 10880 | 192 | return (PAGE_CUR_CONTAIN); | |
| 10881 | 271 | case HA_READ_MBR_INTERSECT: | |
| 10882 | 271 | return (PAGE_CUR_INTERSECT); | |
| 10883 | 70 | case HA_READ_MBR_WITHIN: | |
| 10884 | 70 | return (PAGE_CUR_WITHIN); | |
| 10885 | 41 | case HA_READ_MBR_DISJOINT: | |
| 10886 | 41 | return (PAGE_CUR_DISJOINT); | |
| 10887 | 65 | case HA_READ_MBR_EQUAL: | |
| 10888 | 65 | return (PAGE_CUR_MBR_EQUAL); | |
| 10889 | ✗ | case HA_READ_PREFIX: | |
| 10890 | ✗ | return (PAGE_CUR_UNSUPP); | |
| 10891 | ✗ | case HA_READ_INVALID: | |
| 10892 | ✗ | return (PAGE_CUR_UNSUPP); | |
| 10893 | /* do not use "default:" in order to produce a gcc warning: | ||
| 10894 | enumeration value '...' not handled in switch | ||
| 10895 | (if -Wswitch or -Wall is used) */ | ||
| 10896 | } | ||
| 10897 | |||
| 10898 | ✗ | my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "this functionality"); | |
| 10899 | |||
| 10900 | ✗ | return (PAGE_CUR_UNSUPP); | |
| 10901 | } | ||
| 10902 | |||
| 10903 | #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND) | ||
| 10904 | 79363 | static bool template_new_is_valid(mysql_row_templ_t *t_new, | |
| 10905 | const mysql_row_templ_t *t_saved, | ||
| 10906 | int n_template) { | ||
| 10907 | /* Percona might modify the template field `rec_field_no`, after its creation, | ||
| 10908 | in row0sel.cc:use_secondary_index. | ||
| 10909 | In order to compare the new template and the previous one, we overwrite | ||
| 10910 | `rec_field_no`. | ||
| 10911 | The new template is discarded and used just for debug purposes so we do not | ||
| 10912 | need to restore the previous value. */ | ||
| 10913 |
2/2✓ Branch 0 taken 189767 times.
✓ Branch 1 taken 79363 times.
|
269130 | for (auto i = 0; i < n_template; ++i) { |
| 10914 | 189767 | auto *templ_new = t_new + i; | |
| 10915 | 189767 | const auto *templ_saved = t_saved + i; | |
| 10916 | 189767 | templ_new->rec_field_no = templ_saved->rec_field_no; | |
| 10917 | } | ||
| 10918 | |||
| 10919 | 79363 | return !memcmp(t_new, t_saved, n_template * sizeof(mysql_row_templ_t)); | |
| 10920 | } | ||
| 10921 | #endif | ||
| 10922 | |||
| 10923 | /* | ||
| 10924 | BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED | ||
| 10925 | --------------------------------------------------- | ||
| 10926 | The following does not cover all the details, but explains how we determine | ||
| 10927 | the start of a new SQL statement, and what is associated with it. | ||
| 10928 | |||
| 10929 | For each table in the database the MySQL interpreter may have several | ||
| 10930 | table handle instances in use, also in a single SQL query. For each table | ||
| 10931 | handle instance there is an InnoDB 'm_prebuilt' struct which contains most | ||
| 10932 | of the InnoDB data associated with this table handle instance. | ||
| 10933 | |||
| 10934 | A) if the user has not explicitly set any MySQL table level locks: | ||
| 10935 | |||
| 10936 | 1) MySQL calls ::external_lock to set an 'intention' table level lock on | ||
| 10937 | the table of the handle instance. There we set | ||
| 10938 | m_prebuilt->sql_stat_start = true. The flag sql_stat_start should be set | ||
| 10939 | true if we are taking this table handle instance to use in a new SQL | ||
| 10940 | statement issued by the user. We also increment trx->n_mysql_tables_in_use. | ||
| 10941 | |||
| 10942 | 2) If m_prebuilt->sql_stat_start == true we 'pre-compile' the MySQL search | ||
| 10943 | instructions to m_prebuilt->template of the table handle instance in | ||
| 10944 | ::index_read. The template is used to save CPU time in large joins. | ||
| 10945 | |||
| 10946 | 3) In row_search_for_mysql, if m_prebuilt->sql_stat_start is true, we | ||
| 10947 | allocate a new consistent read view for the trx if it does not yet have one, | ||
| 10948 | or in the case of a locking read, set an InnoDB 'intention' table level | ||
| 10949 | lock on the table. | ||
| 10950 | |||
| 10951 | 4) We do the SELECT. MySQL may repeatedly call ::index_read for the | ||
| 10952 | same table handle instance, if it is a join. | ||
| 10953 | |||
| 10954 | 5) When the SELECT ends, MySQL removes its intention table level locks | ||
| 10955 | in ::external_lock. When trx->n_mysql_tables_in_use drops to zero, | ||
| 10956 | (a) we execute a COMMIT there if the autocommit is on, | ||
| 10957 | (b) we also release possible 'SQL statement level resources' InnoDB may | ||
| 10958 | have for this SQL statement. The MySQL interpreter does NOT execute | ||
| 10959 | autocommit for pure read transactions, though it should. That is why the | ||
| 10960 | table handler in that case has to execute the COMMIT in ::external_lock. | ||
| 10961 | |||
| 10962 | B) If the user has explicitly set MySQL table level locks, then MySQL | ||
| 10963 | does NOT call ::external_lock at the start of the statement. To determine | ||
| 10964 | when we are at the start of a new SQL statement we at the start of | ||
| 10965 | ::index_read also compare the query id to the latest query id where the | ||
| 10966 | table handle instance was used. If it has changed, we know we are at the | ||
| 10967 | start of a new SQL statement. Since the query id can theoretically | ||
| 10968 | overwrap, we use this test only as a secondary way of determining the | ||
| 10969 | start of a new SQL statement. */ | ||
| 10970 | |||
| 10971 | /** Positions an index cursor to the index specified in the handle. Fetches the | ||
| 10972 | row if any. | ||
| 10973 | @return 0, HA_ERR_KEY_NOT_FOUND, or error number */ | ||
| 10974 | |||
| 10975 | 71360326 | int ha_innobase::index_read( | |
| 10976 | uchar *buf, /*!< in/out: buffer for the returned | ||
| 10977 | row */ | ||
| 10978 | const uchar *key_ptr, /*!< in: key value; if this is NULL | ||
| 10979 | we position the cursor at the | ||
| 10980 | start or end of index; this can | ||
| 10981 | also contain an InnoDB row id, in | ||
| 10982 | which case key_len is the InnoDB | ||
| 10983 | row id length; the key value can | ||
| 10984 | also be a prefix of a full key value, | ||
| 10985 | and the last column can be a prefix | ||
| 10986 | of a full column */ | ||
| 10987 | uint key_len, /*!< in: key value length */ | ||
| 10988 | enum ha_rkey_function find_flag) /*!< in: search flags from my_base.h */ | ||
| 10989 | { | ||
| 10990 |
1/2✓ Branch 0 taken 71360533 times.
✗ Branch 1 not taken.
|
71360326 | DBUG_TRACE; |
| 10991 |
3/4✓ Branch 0 taken 68608788 times.
✓ Branch 1 taken 2751745 times.
✓ Branch 2 taken 68608832 times.
✗ Branch 3 not taken.
|
71360533 | DEBUG_SYNC_C("ha_innobase_index_read_begin"); |
| 10992 | |||
| 10993 |
2/4✓ Branch 0 taken 71360543 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 71360555 times.
|
71360577 | ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd)); |
| 10994 |
4/6✓ Branch 0 taken 3819871 times.
✓ Branch 1 taken 67540684 times.
✓ Branch 2 taken 3819871 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 71360552 times.
|
71360555 | ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT); |
| 10995 | |||
| 10996 |
1/2✓ Branch 0 taken 71360566 times.
✗ Branch 1 not taken.
|
71360552 | ha_statistic_increment(&System_status_var::ha_read_key_count); |
| 10997 | |||
| 10998 |
9/14✓ Branch 0 taken 71360564 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 71198248 times.
✓ Branch 3 taken 162316 times.
✓ Branch 4 taken 71198255 times.
✓ Branch 5 taken 162311 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 71198255 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 71360566 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 71360566 times.
|
71360566 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 10999 | m_share->ib_table && m_share->ib_table->is_corrupt)) { | ||
| 11000 | ✗ | return HA_ERR_CRASHED; | |
| 11001 | } | ||
| 11002 | |||
| 11003 | 71360566 | dict_index_t *index = m_prebuilt->index; | |
| 11004 | |||
| 11005 |
5/8✓ Branch 0 taken 71360563 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 71360541 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 71360544 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 71360544 times.
|
71360566 | if (index == nullptr || index->is_corrupted()) { |
| 11006 | ✗ | m_prebuilt->index_usable = false; | |
| 11007 | ✗ | return HA_ERR_CRASHED; | |
| 11008 | } | ||
| 11009 | |||
| 11010 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 71360544 times.
|
71360544 | if (!m_prebuilt->index_usable) { |
| 11011 | ✗ | return index->is_corrupted() ? HA_ERR_INDEX_CORRUPT | |
| 11012 | ✗ | : HA_ERR_TABLE_DEF_CHANGED; | |
| 11013 | } | ||
| 11014 | |||
| 11015 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 71360544 times.
|
71360544 | if (index->type & DICT_FTS) { |
| 11016 | ✗ | return HA_ERR_KEY_NOT_FOUND; | |
| 11017 | } | ||
| 11018 | |||
| 11019 | /* For R-Tree index, we will always place the page lock to | ||
| 11020 | pages being searched */ | ||
| 11021 |
3/4✓ Branch 0 taken 71360538 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 201 times.
✓ Branch 3 taken 71360337 times.
|
71360544 | if (dict_index_is_spatial(index)) { |
| 11022 | 201 | ++m_prebuilt->trx->will_lock; | |
| 11023 | } | ||
| 11024 | |||
| 11025 | /* Note that if the index for which the search template is built is not | ||
| 11026 | necessarily m_prebuilt->index, but can also be the clustered index */ | ||
| 11027 | |||
| 11028 |
7/8✓ Branch 0 taken 48227603 times.
✓ Branch 1 taken 23132935 times.
✓ Branch 2 taken 48227433 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48148174 times.
✓ Branch 5 taken 79259 times.
✓ Branch 6 taken 48148242 times.
✓ Branch 7 taken 23212126 times.
|
71360538 | if (m_prebuilt->sql_stat_start && !can_reuse_mysql_template()) { |
| 11029 |
1/2✓ Branch 0 taken 48148433 times.
✗ Branch 1 not taken.
|
48148242 | build_template(false); |
| 11030 | } | ||
| 11031 | |||
| 11032 | #if defined(UNIV_DEBUG) && !defined(UNIV_DEBUG_VALGRIND) | ||
| 11033 | /* valgrind complains about some of uninitialized bytes. skip it for now. */ | ||
| 11034 |
7/8✓ Branch 0 taken 48227636 times.
✓ Branch 1 taken 23132923 times.
✓ Branch 2 taken 48227631 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 79363 times.
✓ Branch 5 taken 48148268 times.
✓ Branch 6 taken 79363 times.
✓ Branch 7 taken 71281191 times.
|
71360559 | if (m_prebuilt->sql_stat_start && can_reuse_mysql_template()) { |
| 11035 | /* confirm mysql_template contents are same */ | ||
| 11036 | 79363 | const auto n_template_save = m_prebuilt->n_template; | |
| 11037 | 79363 | mysql_row_templ_t *mysql_template_save = m_prebuilt->mysql_template; | |
| 11038 | 79363 | m_prebuilt->mysql_template = nullptr; | |
| 11039 |
1/2✓ Branch 0 taken 79363 times.
✗ Branch 1 not taken.
|
79363 | build_template(false); |
| 11040 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79363 times.
|
79363 | ut_a(m_prebuilt->n_template == n_template_save); |
| 11041 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79363 times.
|
79363 | ut_a(template_new_is_valid(m_prebuilt->mysql_template, mysql_template_save, |
| 11042 | n_template_save)); | ||
| 11043 | 79363 | ut::free(m_prebuilt->mysql_template); | |
| 11044 | 79363 | m_prebuilt->mysql_template = mysql_template_save; | |
| 11045 | } | ||
| 11046 | #endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */ | ||
| 11047 | |||
| 11048 |
2/2✓ Branch 0 taken 67540642 times.
✓ Branch 1 taken 3819912 times.
|
71360554 | if (key_ptr != nullptr) { |
| 11049 | /* Convert the search key value to InnoDB format into | ||
| 11050 | m_prebuilt->search_tuple */ | ||
| 11051 | |||
| 11052 | 67540642 | row_sel_convert_mysql_key_to_innobase( | |
| 11053 | 67540642 | m_prebuilt->search_tuple, m_prebuilt->srch_key_val1, | |
| 11054 |
1/2✓ Branch 0 taken 67540653 times.
✗ Branch 1 not taken.
|
67540642 | m_prebuilt->srch_key_val_len, index, key_ptr, key_len); |
| 11055 | |||
| 11056 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67540653 times.
|
67540653 | assert(m_prebuilt->search_tuple->n_fields > 0); |
| 11057 | } else { | ||
| 11058 | /* We position the cursor to the last or the first entry | ||
| 11059 | in the index */ | ||
| 11060 | |||
| 11061 |
1/2✓ Branch 0 taken 3819870 times.
✗ Branch 1 not taken.
|
3819912 | dtuple_set_n_fields(m_prebuilt->search_tuple, 0); |
| 11062 | } | ||
| 11063 | |||
| 11064 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 71360495 times.
|
71360523 | ut_ad(m_prebuilt->m_mysql_handler == this); |
| 11065 | 71360495 | m_prebuilt->m_stop_tuple_found = false; | |
| 11066 |
6/6✓ Branch 0 taken 373733 times.
✓ Branch 1 taken 70986762 times.
✓ Branch 2 taken 343012 times.
✓ Branch 3 taken 30712 times.
✓ Branch 4 taken 343001 times.
✓ Branch 5 taken 71017485 times.
|
71360495 | if (end_range != nullptr && m_prebuilt->is_reading_range()) { |
| 11067 | 343001 | row_sel_convert_mysql_key_to_innobase( | |
| 11068 | 343001 | m_prebuilt->m_stop_tuple, m_prebuilt->srch_key_val2, | |
| 11069 |
1/2✓ Branch 0 taken 343039 times.
✗ Branch 1 not taken.
|
343001 | m_prebuilt->srch_key_val_len, index, end_range->key, end_range->length); |
| 11070 | } else { | ||
| 11071 |
1/2✓ Branch 0 taken 71017460 times.
✗ Branch 1 not taken.
|
71017485 | dtuple_set_n_fields(m_prebuilt->m_stop_tuple, 0); |
| 11072 | } | ||
| 11073 | |||
| 11074 |
1/2✓ Branch 0 taken 71360361 times.
✗ Branch 1 not taken.
|
71360499 | page_cur_mode_t mode = convert_search_mode_to_innobase(find_flag); |
| 11075 | |||
| 11076 | 71360361 | ulint match_mode = 0; | |
| 11077 | |||
| 11078 |
2/2✓ Branch 0 taken 67419094 times.
✓ Branch 1 taken 3941267 times.
|
71360361 | if (find_flag == HA_READ_KEY_EXACT) { |
| 11079 | 67419094 | match_mode = ROW_SEL_EXACT; | |
| 11080 | |||
| 11081 |
2/2✓ Branch 0 taken 2240 times.
✓ Branch 1 taken 3939027 times.
|
3941267 | } else if (find_flag == HA_READ_PREFIX_LAST) { |
| 11082 | 2240 | match_mode = ROW_SEL_EXACT_PREFIX; | |
| 11083 | } | ||
| 11084 | |||
| 11085 | 71360361 | m_last_match_mode = (uint)match_mode; | |
| 11086 | |||
| 11087 | dberr_t ret; | ||
| 11088 | |||
| 11089 |
1/2✓ Branch 0 taken 71360382 times.
✗ Branch 1 not taken.
|
71360361 | if (mode != PAGE_CUR_UNSUPP) { |
| 11090 |
1/2✓ Branch 0 taken 71360359 times.
✗ Branch 1 not taken.
|
71360382 | ret = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 11091 | |||
| 11092 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 71360359 times.
|
71360359 | if (ret != DB_SUCCESS) { |
| 11093 | ✗ | return convert_error_code_to_mysql(ret, m_prebuilt->table->flags, | |
| 11094 | ✗ | m_user_thd); | |
| 11095 | } | ||
| 11096 | |||
| 11097 |
3/4✓ Branch 0 taken 71360467 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 71154385 times.
✓ Branch 3 taken 206082 times.
|
71360359 | if (!m_prebuilt->table->is_intrinsic()) { |
| 11098 |
3/4✓ Branch 0 taken 71154393 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 71154392 times.
|
71154385 | if (TrxInInnoDB::is_aborted(m_prebuilt->trx)) { |
| 11099 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | innobase_rollback(ht, m_user_thd, false); |
| 11100 | |||
| 11101 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 11102 | } | ||
| 11103 | |||
| 11104 |
1/2✓ Branch 0 taken 71154250 times.
✗ Branch 1 not taken.
|
71154392 | m_prebuilt->ins_sel_stmt = thd_is_ins_sel_stmt(m_user_thd); |
| 11105 | |||
| 11106 |
1/2✓ Branch 0 taken 71154417 times.
✗ Branch 1 not taken.
|
71154250 | ret = row_search_mvcc(buf, mode, m_prebuilt, match_mode, 0); |
| 11107 | |||
| 11108 | } else { | ||
| 11109 |
1/2✓ Branch 0 taken 206099 times.
✗ Branch 1 not taken.
|
206082 | m_prebuilt->session = thd_to_innodb_session(m_user_thd); |
| 11110 | |||
| 11111 |
1/2✓ Branch 0 taken 206099 times.
✗ Branch 1 not taken.
|
206099 | ret = row_search_no_mvcc(buf, mode, m_prebuilt, match_mode, 0); |
| 11112 | } | ||
| 11113 | |||
| 11114 |
1/2✓ Branch 0 taken 71360576 times.
✗ Branch 1 not taken.
|
71360516 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 11115 | } else { | ||
| 11116 | ✗ | ret = DB_UNSUPPORTED; | |
| 11117 | } | ||
| 11118 | |||
| 11119 |
9/14✓ Branch 0 taken 71360547 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 71198244 times.
✓ Branch 3 taken 162303 times.
✓ Branch 4 taken 71198254 times.
✓ Branch 5 taken 162301 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 71198254 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 71360555 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 71360555 times.
|
71360555 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 11120 | m_share->ib_table && m_share->ib_table->is_corrupt)) { | ||
| 11121 | ✗ | return HA_ERR_CRASHED; | |
| 11122 | } | ||
| 11123 | |||
| 11124 |
2/4✓ Branch 0 taken 71360570 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 71360570 times.
|
71360555 | DBUG_EXECUTE_IF("ib_select_query_failure", ret = DB_ERROR;); |
| 11125 | |||
| 11126 | int error; | ||
| 11127 | |||
| 11128 |
5/6✓ Branch 0 taken 50028723 times.
✓ Branch 1 taken 19957355 times.
✓ Branch 2 taken 1373987 times.
✓ Branch 3 taken 184 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 321 times.
|
71360570 | switch (ret) { |
| 11129 | 50028723 | case DB_SUCCESS: | |
| 11130 | 50028723 | error = 0; | |
| 11131 |
2/2✓ Branch 0 taken 46405572 times.
✓ Branch 1 taken 3623151 times.
|
50028723 | if (m_prebuilt->table->is_system_table) { |
| 11132 |
1/2✓ Branch 0 taken 46405571 times.
✗ Branch 1 not taken.
|
46405574 | srv_stats.n_system_rows_read.add( |
| 11133 |
1/2✓ Branch 0 taken 46405574 times.
✗ Branch 1 not taken.
|
46405572 | thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1); |
| 11134 | } else { | ||
| 11135 |
2/4✓ Branch 0 taken 3623149 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3623147 times.
✗ Branch 3 not taken.
|
3623151 | srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd), |
| 11136 | 1); | ||
| 11137 | } | ||
| 11138 | 50028718 | break; | |
| 11139 | |||
| 11140 | 19957355 | case DB_RECORD_NOT_FOUND: | |
| 11141 | 19957355 | error = HA_ERR_KEY_NOT_FOUND; | |
| 11142 | 19957355 | break; | |
| 11143 | |||
| 11144 | 1373987 | case DB_END_OF_INDEX: | |
| 11145 | 1373987 | error = HA_ERR_KEY_NOT_FOUND; | |
| 11146 | 1373987 | break; | |
| 11147 | |||
| 11148 | 184 | case DB_TABLESPACE_DELETED: | |
| 11149 | 184 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 11150 |
1/2✓ Branch 0 taken 184 times.
✗ Branch 1 not taken.
|
184 | ER_TABLESPACE_DISCARDED, table->s->table_name.str); |
| 11151 | |||
| 11152 | 184 | error = HA_ERR_NO_SUCH_TABLE; | |
| 11153 | 184 | break; | |
| 11154 | |||
| 11155 | ✗ | case DB_TABLESPACE_NOT_FOUND: | |
| 11156 | |||
| 11157 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 11158 | ✗ | ER_TABLESPACE_MISSING, table->s->table_name.str); | |
| 11159 | |||
| 11160 | ✗ | error = HA_ERR_TABLESPACE_MISSING; | |
| 11161 | ✗ | break; | |
| 11162 | |||
| 11163 | 321 | default: | |
| 11164 |
1/2✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
|
321 | error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags, |
| 11165 | m_user_thd); | ||
| 11166 | |||
| 11167 | 309 | break; | |
| 11168 | } | ||
| 11169 | |||
| 11170 | 71360553 | return error; | |
| 11171 | 71360554 | } | |
| 11172 | |||
| 11173 | /** The following functions works like index_read, but it find the last | ||
| 11174 | row with the current key value or prefix. | ||
| 11175 | @return 0, HA_ERR_KEY_NOT_FOUND, or an error code */ | ||
| 11176 | |||
| 11177 | 482 | int ha_innobase::index_read_last( | |
| 11178 | uchar *buf, /*!< out: fetched row */ | ||
| 11179 | const uchar *key_ptr, /*!< in: key value, or a prefix of a full | ||
| 11180 | key value */ | ||
| 11181 | uint key_len) /*!< in: length of the key val or prefix | ||
| 11182 | in bytes */ | ||
| 11183 | { | ||
| 11184 | 482 | return (index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST)); | |
| 11185 | } | ||
| 11186 | |||
| 11187 | /** Get the index for a handle. Does not change active index. | ||
| 11188 | @return NULL or index instance. */ | ||
| 11189 | |||
| 11190 | 131854222 | dict_index_t *ha_innobase::innobase_get_index( | |
| 11191 | uint keynr) /*!< in: use this index; MAX_KEY means always | ||
| 11192 | clustered index, even if it was internally | ||
| 11193 | generated by InnoDB */ | ||
| 11194 | { | ||
| 11195 | KEY *key; | ||
| 11196 | dict_index_t *index; | ||
| 11197 | |||
| 11198 |
1/2✓ Branch 0 taken 131854656 times.
✗ Branch 1 not taken.
|
131854222 | DBUG_TRACE; |
| 11199 | |||
| 11200 |
4/4✓ Branch 0 taken 131401740 times.
✓ Branch 1 taken 452916 times.
✓ Branch 2 taken 131401703 times.
✓ Branch 3 taken 37 times.
|
131854656 | if (keynr != MAX_KEY && table->s->keys > 0) { |
| 11201 | 131401703 | key = table->key_info + keynr; | |
| 11202 | |||
| 11203 | 131401703 | index = innobase_index_lookup(m_share, keynr); | |
| 11204 | |||
| 11205 |
1/2✓ Branch 0 taken 131401658 times.
✗ Branch 1 not taken.
|
131401532 | if (index != nullptr) { |
| 11206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 131401600 times.
|
131401658 | ut_a(ut_strcmp(index->name, key->name) == 0); |
| 11207 | } else { | ||
| 11208 | /* Can't find index with keynr in the translation | ||
| 11209 | table. Only print message if the index translation | ||
| 11210 | table exists */ | ||
| 11211 | ✗ | if (m_share->idx_trans_tbl.index_mapping != nullptr) { | |
| 11212 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_WITH_KEY_NO, | |
| 11213 | key ? key->name : "NULL", keynr, | ||
| 11214 | m_prebuilt->table->name.m_name); | ||
| 11215 | } | ||
| 11216 | |||
| 11217 | ✗ | index = dict_table_get_index_on_name(m_prebuilt->table, key->name); | |
| 11218 | } | ||
| 11219 | } else { | ||
| 11220 | 452953 | key = nullptr; | |
| 11221 |
1/2✓ Branch 0 taken 452922 times.
✗ Branch 1 not taken.
|
452953 | index = m_prebuilt->table->first_index(); |
| 11222 | } | ||
| 11223 | |||
| 11224 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 131854522 times.
|
131854522 | if (index == nullptr) { |
| 11225 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX_FROM_DICT_CACHE, keynr, | |
| 11226 | key ? key->name : "NULL", m_prebuilt->table->name.m_name); | ||
| 11227 | } | ||
| 11228 | |||
| 11229 | 131854661 | return index; | |
| 11230 | 131854522 | } | |
| 11231 | |||
| 11232 | /** Changes the active index of a handle. | ||
| 11233 | @return 0 or error code */ | ||
| 11234 | 107422659 | int ha_innobase::change_active_index( | |
| 11235 | uint keynr) /*!< in: use this index; MAX_KEY means always clustered | ||
| 11236 | index, even if it was internally generated by | ||
| 11237 | InnoDB */ | ||
| 11238 | { | ||
| 11239 |
1/2✓ Branch 0 taken 107422844 times.
✗ Branch 1 not taken.
|
107422659 | DBUG_TRACE; |
| 11240 | |||
| 11241 |
8/14✓ Branch 0 taken 107422813 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 107422823 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 107422828 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 107422828 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 107422844 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 107422844 times.
|
107422844 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 11242 | m_share->ib_table && m_share->ib_table->is_corrupt)) | ||
| 11243 | ✗ | return HA_ERR_CRASHED; | |
| 11244 | |||
| 11245 |
2/4✓ Branch 0 taken 107422832 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107422757 times.
|
107422844 | ut_ad(m_user_thd == ha_thd()); |
| 11246 |
2/4✓ Branch 0 taken 107422835 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 107422818 times.
|
107422757 | ut_a(m_prebuilt->trx == thd_to_trx(m_user_thd)); |
| 11247 | |||
| 11248 |
1/2✓ Branch 0 taken 107422695 times.
✗ Branch 1 not taken.
|
107422818 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 11249 | |||
| 11250 |
8/10✓ Branch 0 taken 107422739 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 107277670 times.
✓ Branch 3 taken 145069 times.
✓ Branch 4 taken 107277695 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 107277693 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 107422762 times.
|
107422695 | if (!m_prebuilt->table->is_intrinsic() && trx_in_innodb.is_aborted()) { |
| 11251 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innobase_rollback(ht, m_user_thd, false); |
| 11252 | |||
| 11253 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); |
| 11254 | } | ||
| 11255 | |||
| 11256 | 107422762 | active_index = keynr; | |
| 11257 | |||
| 11258 |
1/2✓ Branch 0 taken 107422845 times.
✗ Branch 1 not taken.
|
107422762 | m_prebuilt->index = innobase_get_index(keynr); |
| 11259 | |||
| 11260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 107422845 times.
|
107422845 | if (m_prebuilt->index == nullptr) { |
| 11261 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_ACTIVE_INDEX_CHANGE_FAILED, keynr); | |
| 11262 | ✗ | m_prebuilt->index_usable = false; | |
| 11263 | ✗ | return 1; | |
| 11264 | } | ||
| 11265 | |||
| 11266 |
1/2✓ Branch 0 taken 107422724 times.
✗ Branch 1 not taken.
|
107422845 | m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx); |
| 11267 | |||
| 11268 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 107422703 times.
|
107422724 | if (!m_prebuilt->index_usable) { |
| 11269 |
3/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 9 times.
|
21 | if (m_prebuilt->index->is_corrupted()) { |
| 11270 | char table_name[MAX_FULL_NAME_LEN + 1]; | ||
| 11271 | |||
| 11272 | 12 | innobase_format_name(table_name, sizeof table_name, | |
| 11273 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | m_prebuilt->index->table->name.m_name); |
| 11274 | |||
| 11275 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
12 | if (m_prebuilt->index->is_clustered()) { |
| 11276 | ✗ | ut_ad(m_prebuilt->table->is_corrupted()); | |
| 11277 | ✗ | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, | |
| 11278 | HA_ERR_TABLE_CORRUPT, | ||
| 11279 | "InnoDB: Table %s is corrupted.", table_name); | ||
| 11280 | ✗ | return HA_ERR_TABLE_CORRUPT; | |
| 11281 | } else { | ||
| 11282 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, |
| 11283 | HA_ERR_INDEX_CORRUPT, | ||
| 11284 | "InnoDB: Index %s for table %s is" | ||
| 11285 | " marked as corrupted", | ||
| 11286 | 12 | m_prebuilt->index->name(), table_name); | |
| 11287 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | my_error(ER_INDEX_CORRUPT, MYF(0), m_prebuilt->index->name()); |
| 11288 | 12 | return HA_ERR_INDEX_CORRUPT; | |
| 11289 | } | ||
| 11290 | } else { | ||
| 11291 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, |
| 11292 | HA_ERR_TABLE_DEF_CHANGED, | ||
| 11293 | "InnoDB: insufficient history for index %u", keynr); | ||
| 11294 | } | ||
| 11295 | |||
| 11296 | /* The caller seems to ignore this. Thus, we must check | ||
| 11297 | this again in row_search_for_mysql(). */ | ||
| 11298 | 9 | return HA_ERR_TABLE_DEF_CHANGED; | |
| 11299 | } | ||
| 11300 | |||
| 11301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 107422702 times.
|
107422703 | ut_a(m_prebuilt->search_tuple != nullptr); |
| 11302 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 107422742 times.
|
107422702 | ut_a(m_prebuilt->m_stop_tuple != nullptr); |
| 11303 | |||
| 11304 | /* Initialization of search_tuple is not needed for FT index | ||
| 11305 | since FT search returns rank only. In addition engine should | ||
| 11306 | be able to retrieve FTS_DOC_ID column value if necessary. */ | ||
| 11307 |
2/2✓ Branch 0 taken 1896 times.
✓ Branch 1 taken 107420846 times.
|
107422742 | if ((m_prebuilt->index->type & DICT_FTS)) { |
| 11308 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | if (table->fts_doc_id_field && |
| 11309 | 134 | bitmap_is_set(table->read_set, | |
| 11310 |
4/4✓ Branch 0 taken 134 times.
✓ Branch 1 taken 1762 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1858 times.
|
2030 | table->fts_doc_id_field->field_index()) && |
| 11311 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 96 times.
|
134 | m_prebuilt->read_just_key) { |
| 11312 | 38 | m_prebuilt->fts_doc_id_in_read_set = true; | |
| 11313 | } | ||
| 11314 | } else { | ||
| 11315 |
1/2✓ Branch 0 taken 107420944 times.
✗ Branch 1 not taken.
|
107420846 | m_prebuilt->init_search_tuples_types(); |
| 11316 | |||
| 11317 | /* If it's FTS query and FTS_DOC_ID exists FTS_DOC_ID field is | ||
| 11318 | always added to read_set. */ | ||
| 11319 | 107420944 | m_prebuilt->fts_doc_id_in_read_set = | |
| 11320 |
4/4✓ Branch 0 taken 867054 times.
✓ Branch 1 taken 106553890 times.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 867000 times.
|
107420998 | (m_prebuilt->read_just_key && table->fts_doc_id_field && |
| 11321 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 3 times.
|
54 | m_prebuilt->in_fts_query); |
| 11322 | } | ||
| 11323 | |||
| 11324 | /* MySQL changes the active index for a handle also during some | ||
| 11325 | queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX() | ||
| 11326 | and then calculates the sum. Previously we played safe and used | ||
| 11327 | the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary | ||
| 11328 | copying. Starting from MySQL-4.1 we use a more efficient flag here. */ | ||
| 11329 | |||
| 11330 |
1/2✓ Branch 0 taken 107422831 times.
✗ Branch 1 not taken.
|
107422840 | build_template(false); |
| 11331 | |||
| 11332 | 107422831 | return 0; | |
| 11333 | 107422854 | } | |
| 11334 | |||
| 11335 | /** Reads the next or previous row from a cursor, which must have previously | ||
| 11336 | been positioned using index_read. | ||
| 11337 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 11338 | |||
| 11339 | 316467105 | int ha_innobase::general_fetch( | |
| 11340 | uchar *buf, /*!< in/out: buffer for next row in MySQL | ||
| 11341 | format */ | ||
| 11342 | uint direction, /*!< in: ROW_SEL_NEXT or ROW_SEL_PREV */ | ||
| 11343 | uint match_mode) /*!< in: 0, ROW_SEL_EXACT, or | ||
| 11344 | ROW_SEL_EXACT_PREFIX */ | ||
| 11345 | { | ||
| 11346 |
1/2✓ Branch 0 taken 316467230 times.
✗ Branch 1 not taken.
|
316467105 | DBUG_TRACE; |
| 11347 | |||
| 11348 |
8/14✓ Branch 0 taken 316467235 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 315696039 times.
✓ Branch 3 taken 771196 times.
✓ Branch 4 taken 315696050 times.
✓ Branch 5 taken 771180 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 315696050 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 316467230 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 316467230 times.
|
316467230 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 11349 | m_share->ib_table && m_share->ib_table->is_corrupt)) | ||
| 11350 | ✗ | return HA_ERR_CRASHED; | |
| 11351 | |||
| 11352 | 316467230 | const trx_t *trx = m_prebuilt->trx; | |
| 11353 | |||
| 11354 |
2/4✓ Branch 0 taken 316466725 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 316466910 times.
|
316467230 | ut_ad(trx == thd_to_trx(m_user_thd)); |
| 11355 | |||
| 11356 |
1/2✓ Branch 0 taken 316466890 times.
✗ Branch 1 not taken.
|
316466910 | bool intrinsic = m_prebuilt->table->is_intrinsic(); |
| 11357 | |||
| 11358 |
5/8✓ Branch 0 taken 311144371 times.
✓ Branch 1 taken 5322519 times.
✓ Branch 2 taken 311144254 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 311144254 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 316466773 times.
|
316466890 | if (!intrinsic && TrxInInnoDB::is_aborted(trx)) { |
| 11359 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 11360 | |||
| 11361 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 11362 | } | ||
| 11363 | |||
| 11364 |
1/2✓ Branch 0 taken 316466596 times.
✗ Branch 1 not taken.
|
316466773 | auto ret = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 11365 | |||
| 11366 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 316466596 times.
|
316466596 | if (ret != DB_SUCCESS) { |
| 11367 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 11368 | } | ||
| 11369 | |||
| 11370 |
2/2✓ Branch 0 taken 311144141 times.
✓ Branch 1 taken 5322455 times.
|
316466596 | if (!intrinsic) { |
| 11371 |
1/2✓ Branch 0 taken 311143913 times.
✗ Branch 1 not taken.
|
311144141 | ret = row_search_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode, |
| 11372 | direction); | ||
| 11373 | |||
| 11374 | } else { | ||
| 11375 |
1/2✓ Branch 0 taken 5322554 times.
✗ Branch 1 not taken.
|
5322455 | ret = row_search_no_mvcc(buf, PAGE_CUR_UNSUPP, m_prebuilt, match_mode, |
| 11376 | direction); | ||
| 11377 | } | ||
| 11378 | |||
| 11379 |
1/2✓ Branch 0 taken 316467153 times.
✗ Branch 1 not taken.
|
316466467 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 11380 | |||
| 11381 | int error; | ||
| 11382 | |||
| 11383 |
4/6✓ Branch 0 taken 295517002 times.
✓ Branch 1 taken 18509768 times.
✓ Branch 2 taken 2440238 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 145 times.
|
316467153 | switch (ret) { |
| 11384 | 295517002 | case DB_SUCCESS: | |
| 11385 | 295517002 | error = 0; | |
| 11386 |
2/2✓ Branch 0 taken 228124356 times.
✓ Branch 1 taken 67392646 times.
|
295517002 | if (m_prebuilt->table->is_system_table) { |
| 11387 |
1/2✓ Branch 0 taken 228124362 times.
✗ Branch 1 not taken.
|
228124359 | srv_stats.n_system_rows_read.add( |
| 11388 |
1/2✓ Branch 0 taken 228124359 times.
✗ Branch 1 not taken.
|
228124356 | thd_get_thread_id(m_prebuilt->trx->mysql_thd), 1); |
| 11389 | } else { | ||
| 11390 |
2/4✓ Branch 0 taken 67392442 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 67392602 times.
✗ Branch 3 not taken.
|
67392646 | srv_stats.n_rows_read.add(thd_get_thread_id(m_prebuilt->trx->mysql_thd), |
| 11391 | 1); | ||
| 11392 | } | ||
| 11393 | 295516964 | break; | |
| 11394 | 18509768 | case DB_RECORD_NOT_FOUND: | |
| 11395 | 18509768 | error = HA_ERR_END_OF_FILE; | |
| 11396 | 18509768 | break; | |
| 11397 | 2440238 | case DB_END_OF_INDEX: | |
| 11398 | 2440238 | error = HA_ERR_END_OF_FILE; | |
| 11399 | 2440238 | break; | |
| 11400 | ✗ | case DB_TABLESPACE_DELETED: | |
| 11401 | ✗ | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 11402 | ✗ | table->s->table_name.str); | |
| 11403 | |||
| 11404 | ✗ | error = HA_ERR_NO_SUCH_TABLE; | |
| 11405 | ✗ | break; | |
| 11406 | ✗ | case DB_TABLESPACE_NOT_FOUND: | |
| 11407 | |||
| 11408 | ✗ | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING, | |
| 11409 | ✗ | table->s->table_name.str); | |
| 11410 | |||
| 11411 | ✗ | error = HA_ERR_TABLESPACE_MISSING; | |
| 11412 | ✗ | break; | |
| 11413 | 145 | default: | |
| 11414 |
1/2✓ Branch 0 taken 97 times.
✗ Branch 1 not taken.
|
145 | error = convert_error_code_to_mysql(ret, m_prebuilt->table->flags, |
| 11415 | m_user_thd); | ||
| 11416 | |||
| 11417 | 97 | break; | |
| 11418 | } | ||
| 11419 | |||
| 11420 | 316467067 | return error; | |
| 11421 | 316467067 | } | |
| 11422 | |||
| 11423 | /** Reads the next row from a cursor, which must have previously been | ||
| 11424 | positioned using index_read. | ||
| 11425 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 11426 | |||
| 11427 | 18997859 | int ha_innobase::index_next(uchar *buf) /*!< in/out: buffer for next row in | |
| 11428 | MySQL format */ | ||
| 11429 | { | ||
| 11430 | 18997859 | ha_statistic_increment(&System_status_var::ha_read_next_count); | |
| 11431 | |||
| 11432 | 18997857 | return (general_fetch(buf, ROW_SEL_NEXT, 0)); | |
| 11433 | } | ||
| 11434 | |||
| 11435 | /** Reads the next row matching to the key value given as the parameter. | ||
| 11436 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 11437 | |||
| 11438 | 109104060 | int ha_innobase::index_next_same(uchar *buf, /*!< in/out: buffer for the row */ | |
| 11439 | const uchar *, /*!< in: key value */ | ||
| 11440 | uint) /*!< in: key value length */ | ||
| 11441 | { | ||
| 11442 | 109104060 | ha_statistic_increment(&System_status_var::ha_read_next_count); | |
| 11443 | |||
| 11444 | 109104066 | return (general_fetch(buf, ROW_SEL_NEXT, m_last_match_mode)); | |
| 11445 | } | ||
| 11446 | |||
| 11447 | /** Reads the previous row from a cursor, which must have previously been | ||
| 11448 | positioned using index_read. | ||
| 11449 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 11450 | |||
| 11451 | 19779 | int ha_innobase::index_prev( | |
| 11452 | uchar *buf) /*!< in/out: buffer for previous row in MySQL format */ | ||
| 11453 | { | ||
| 11454 | 19779 | ha_statistic_increment(&System_status_var::ha_read_prev_count); | |
| 11455 | |||
| 11456 | 19779 | return (general_fetch(buf, ROW_SEL_PREV, 0)); | |
| 11457 | } | ||
| 11458 | |||
| 11459 | /** Positions a cursor on the first record in an index and reads the | ||
| 11460 | corresponding row to buf. | ||
| 11461 | @return 0, HA_ERR_END_OF_FILE, or error code */ | ||
| 11462 | |||
| 11463 | 3812916 | int ha_innobase::index_first(uchar *buf) /*!< in/out: buffer for the row */ | |
| 11464 | { | ||
| 11465 |
1/2✓ Branch 0 taken 3812935 times.
✗ Branch 1 not taken.
|
3812916 | DBUG_TRACE; |
| 11466 | |||
| 11467 |
1/2✓ Branch 0 taken 3812936 times.
✗ Branch 1 not taken.
|
3812935 | ha_statistic_increment(&System_status_var::ha_read_first_count); |
| 11468 | |||
| 11469 |
1/2✓ Branch 0 taken 3812928 times.
✗ Branch 1 not taken.
|
3812936 | int error = index_read(buf, nullptr, 0, HA_READ_AFTER_KEY); |
| 11470 | |||
| 11471 | /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ | ||
| 11472 | |||
| 11473 |
2/2✓ Branch 0 taken 1297703 times.
✓ Branch 1 taken 2515225 times.
|
3812928 | if (error == HA_ERR_KEY_NOT_FOUND) { |
| 11474 | 1297703 | error = HA_ERR_END_OF_FILE; | |
| 11475 | } | ||
| 11476 | |||
| 11477 | 3812929 | return error; | |
| 11478 | 3812928 | } | |
| 11479 | |||
| 11480 | /** Positions a cursor on the last record in an index and reads the | ||
| 11481 | corresponding row to buf. | ||
| 11482 | @return 0, HA_ERR_END_OF_FILE, or error code */ | ||
| 11483 | |||
| 11484 | 6934 | int ha_innobase::index_last(uchar *buf) /*!< in/out: buffer for the row */ | |
| 11485 | { | ||
| 11486 |
1/2✓ Branch 0 taken 6934 times.
✗ Branch 1 not taken.
|
6934 | DBUG_TRACE; |
| 11487 | |||
| 11488 |
1/2✓ Branch 0 taken 6934 times.
✗ Branch 1 not taken.
|
6934 | ha_statistic_increment(&System_status_var::ha_read_last_count); |
| 11489 | |||
| 11490 |
1/2✓ Branch 0 taken 6934 times.
✗ Branch 1 not taken.
|
6934 | int error = index_read(buf, nullptr, 0, HA_READ_BEFORE_KEY); |
| 11491 | |||
| 11492 | /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ | ||
| 11493 | |||
| 11494 |
2/2✓ Branch 0 taken 1671 times.
✓ Branch 1 taken 5263 times.
|
6934 | if (error == HA_ERR_KEY_NOT_FOUND) { |
| 11495 | 1671 | error = HA_ERR_END_OF_FILE; | |
| 11496 | } | ||
| 11497 | |||
| 11498 | 6934 | return error; | |
| 11499 | 6934 | } | |
| 11500 | |||
| 11501 | 198 | int ha_innobase::sample_init(void *&scan_ctx, double sampling_percentage, | |
| 11502 | int sampling_seed, | ||
| 11503 | enum_sampling_method sampling_method, | ||
| 11504 | const bool tablesample) { | ||
| 11505 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | ut_ad(table_share->is_missing_primary_key() == |
| 11506 | (bool)m_prebuilt->clust_index_was_generated); | ||
| 11507 | |||
| 11508 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | ut_ad(sampling_percentage >= 0.0); |
| 11509 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | ut_ad(sampling_percentage <= 100.0); |
| 11510 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | ut_ad(sampling_method == enum_sampling_method::SYSTEM); |
| 11511 | |||
| 11512 |
2/4✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
✗ Branch 3 not taken.
|
198 | if (sampling_percentage <= 0.0 || sampling_percentage > 100.0 || |
| 11513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 198 times.
|
198 | sampling_method != enum_sampling_method::SYSTEM) { |
| 11514 | ✗ | return 0; | |
| 11515 | } | ||
| 11516 | |||
| 11517 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 197 times.
|
198 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 11518 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ib_senderrf(ha_thd(), IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, |
| 11519 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | m_prebuilt->table->name.m_name); |
| 11520 | |||
| 11521 | 1 | return HA_ERR_NO_SUCH_TABLE; | |
| 11522 | } | ||
| 11523 | |||
| 11524 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | int err = change_active_index(table_share->primary_key); |
| 11525 | |||
| 11526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
|
197 | if (err != 0) { |
| 11527 | ✗ | return err; | |
| 11528 | } | ||
| 11529 | |||
| 11530 | 197 | trx_t *trx{nullptr}; | |
| 11531 | |||
| 11532 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
|
197 | if (tablesample) { |
| 11533 | ✗ | update_thd(); | |
| 11534 | |||
| 11535 | ✗ | trx = m_prebuilt->trx; | |
| 11536 | ✗ | trx_start_if_not_started_xa(trx, false, UT_LOCATION_HERE); | |
| 11537 | |||
| 11538 | ✗ | if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED) { | |
| 11539 | ✗ | trx_assign_read_view(trx); | |
| 11540 | } | ||
| 11541 | } | ||
| 11542 | |||
| 11543 | /* Parallel read is not currently supported for sampling. */ | ||
| 11544 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | size_t max_threads = Parallel_reader::available_threads(1, false); |
| 11545 | |||
| 11546 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
|
197 | if (max_threads == 0) { |
| 11547 | ✗ | return HA_ERR_SAMPLING_INIT_FAILED; | |
| 11548 | } | ||
| 11549 | |||
| 11550 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | Histogram_sampler *sampler = ut::new_withkey<Histogram_sampler>( |
| 11551 | 197 | UT_NEW_THIS_FILE_PSI_KEY, max_threads, sampling_seed, sampling_percentage, | |
| 11552 | sampling_method); | ||
| 11553 | |||
| 11554 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
|
197 | if (sampler == nullptr) { |
| 11555 | ✗ | Parallel_reader::release_threads(max_threads); | |
| 11556 | ✗ | return HA_ERR_OUT_OF_MEM; | |
| 11557 | } | ||
| 11558 | |||
| 11559 | 197 | scan_ctx = static_cast<void *>(sampler); | |
| 11560 | |||
| 11561 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | auto index = m_prebuilt->table->first_index(); |
| 11562 | |||
| 11563 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | auto success = sampler->init(trx, index, m_prebuilt); |
| 11564 | |||
| 11565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
|
197 | if (!success) { |
| 11566 | ✗ | return (HA_ERR_SAMPLING_INIT_FAILED); | |
| 11567 | } | ||
| 11568 | |||
| 11569 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | dberr_t db_err = sampler->run(); |
| 11570 | |||
| 11571 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
|
197 | if (db_err != DB_SUCCESS) { |
| 11572 | ✗ | return (convert_error_code_to_mysql(db_err, 0, ha_thd())); | |
| 11573 | } | ||
| 11574 | |||
| 11575 | 197 | return (0); | |
| 11576 | } | ||
| 11577 | |||
| 11578 | 40583 | int ha_innobase::sample_next(void *scan_ctx, uchar *buf) { | |
| 11579 | 40583 | dberr_t err = DB_SUCCESS; | |
| 11580 | |||
| 11581 | 40583 | Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx); | |
| 11582 | |||
| 11583 | 40583 | sampler->set(buf); | |
| 11584 | |||
| 11585 | /** Buffer rows one by one */ | ||
| 11586 | 40583 | err = sampler->buffer_next(); | |
| 11587 | |||
| 11588 |
2/2✓ Branch 0 taken 194 times.
✓ Branch 1 taken 40389 times.
|
40583 | if (err == DB_END_OF_INDEX) { |
| 11589 | 194 | return HA_ERR_END_OF_FILE; | |
| 11590 | } | ||
| 11591 | |||
| 11592 | 40389 | return (convert_error_code_to_mysql(err, 0, ha_thd())); | |
| 11593 | } | ||
| 11594 | |||
| 11595 | 197 | int ha_innobase::sample_end(void *scan_ctx) { | |
| 11596 | 197 | Histogram_sampler *sampler = static_cast<Histogram_sampler *>(scan_ctx); | |
| 11597 | |||
| 11598 | 197 | ut::delete_(sampler); | |
| 11599 | |||
| 11600 | 197 | return 0; | |
| 11601 | } | ||
| 11602 | |||
| 11603 | 416932 | int ha_innobase::read_range_first(const key_range *start_key, | |
| 11604 | const key_range *end_key, bool eq_range_arg, | ||
| 11605 | bool sorted) { | ||
| 11606 |
1/2✓ Branch 0 taken 416974 times.
✗ Branch 1 not taken.
|
416932 | auto guard = m_prebuilt->get_is_reading_range_guard(); |
| 11607 |
1/2✓ Branch 0 taken 417023 times.
✗ Branch 1 not taken.
|
833997 | return handler::read_range_first(start_key, end_key, eq_range_arg, sorted); |
| 11608 | 417023 | } | |
| 11609 | |||
| 11610 | 3040875 | int ha_innobase::read_range_next() { | |
| 11611 |
1/2✓ Branch 0 taken 3040875 times.
✗ Branch 1 not taken.
|
3040875 | auto guard = m_prebuilt->get_is_reading_range_guard(); |
| 11612 |
1/2✓ Branch 0 taken 3040876 times.
✗ Branch 1 not taken.
|
6081751 | return (handler::read_range_next()); |
| 11613 | 3040876 | } | |
| 11614 | |||
| 11615 | /** Initialize a table scan. | ||
| 11616 | @param[in] scan whether this is a second call to rnd_init() | ||
| 11617 | without rnd_end() in between | ||
| 11618 | @return 0 or error number */ | ||
| 11619 | 3328201 | int ha_innobase::rnd_init(bool scan) { | |
| 11620 |
1/2✓ Branch 0 taken 3328208 times.
✗ Branch 1 not taken.
|
3328201 | DBUG_TRACE; |
| 11621 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3328204 times.
|
3328208 | assert(table_share->is_missing_primary_key() == |
| 11622 | (bool)m_prebuilt->clust_index_was_generated); | ||
| 11623 | |||
| 11624 |
1/2✓ Branch 0 taken 3328204 times.
✗ Branch 1 not taken.
|
3328204 | int err = change_active_index(table_share->primary_key); |
| 11625 | |||
| 11626 | /* Don't use semi-consistent read in random row reads (by position). | ||
| 11627 | This means we must disable semi_consistent_read if scan is false */ | ||
| 11628 | |||
| 11629 |
2/2✓ Branch 0 taken 215236 times.
✓ Branch 1 taken 3112968 times.
|
3328204 | if (!scan) { |
| 11630 | 215236 | m_prebuilt->row_read_type = ROW_READ_WITH_LOCKS; | |
| 11631 | } | ||
| 11632 | |||
| 11633 | 3328204 | m_start_of_scan = true; | |
| 11634 | 3328208 | return err; | |
| 11635 | 3328204 | } | |
| 11636 | |||
| 11637 | /** Ends a table scan. | ||
| 11638 | @return 0 or error number */ | ||
| 11639 | |||
| 11640 | 1985664 | int ha_innobase::rnd_end(void) { return (index_end()); } | |
| 11641 | |||
| 11642 | /** Reads the next row in a table scan (also used to read the FIRST row | ||
| 11643 | in a table scan). | ||
| 11644 | @return 0, HA_ERR_END_OF_FILE, or error number */ | ||
| 11645 | |||
| 11646 | 190783849 | int ha_innobase::rnd_next(uchar *buf) /*!< in/out: returns the row in this | |
| 11647 | buffer, in MySQL format */ | ||
| 11648 | { | ||
| 11649 | int error; | ||
| 11650 | |||
| 11651 |
1/2✓ Branch 0 taken 190784516 times.
✗ Branch 1 not taken.
|
190783849 | DBUG_TRACE; |
| 11652 | |||
| 11653 |
1/2✓ Branch 0 taken 190784536 times.
✗ Branch 1 not taken.
|
190784516 | ha_statistic_increment(&System_status_var::ha_read_rnd_next_count); |
| 11654 | |||
| 11655 |
2/2✓ Branch 0 taken 3112961 times.
✓ Branch 1 taken 187671575 times.
|
190784536 | if (m_start_of_scan) { |
| 11656 |
1/2✓ Branch 0 taken 3112958 times.
✗ Branch 1 not taken.
|
3112961 | error = index_first(buf); |
| 11657 | |||
| 11658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3112958 times.
|
3112958 | if (error == HA_ERR_KEY_NOT_FOUND) { |
| 11659 | ✗ | error = HA_ERR_END_OF_FILE; | |
| 11660 | } | ||
| 11661 | |||
| 11662 | 3112958 | m_start_of_scan = false; | |
| 11663 | } else { | ||
| 11664 |
1/2✓ Branch 0 taken 187670946 times.
✗ Branch 1 not taken.
|
187671575 | error = general_fetch(buf, ROW_SEL_NEXT, 0); |
| 11665 | } | ||
| 11666 | |||
| 11667 | 190784658 | return error; | |
| 11668 | 190783904 | } | |
| 11669 | |||
| 11670 | /** Fetches a row from the table based on a row reference. | ||
| 11671 | @return 0, HA_ERR_KEY_NOT_FOUND, or error code */ | ||
| 11672 | |||
| 11673 | 957701 | int ha_innobase::rnd_pos( | |
| 11674 | uchar *buf, /*!< in/out: buffer for the row */ | ||
| 11675 | uchar *pos) /*!< in: primary key value of the row in the | ||
| 11676 | MySQL format, or the row id if the clustered | ||
| 11677 | index was internally generated by InnoDB; the | ||
| 11678 | length of data in pos has to be ref_length */ | ||
| 11679 | { | ||
| 11680 |
1/2✓ Branch 0 taken 957705 times.
✗ Branch 1 not taken.
|
957701 | DBUG_TRACE; |
| 11681 |
1/2✓ Branch 0 taken 957705 times.
✗ Branch 1 not taken.
|
957705 | DBUG_DUMP("key", pos, ref_length); |
| 11682 | |||
| 11683 |
1/2✓ Branch 0 taken 957704 times.
✗ Branch 1 not taken.
|
957705 | ha_statistic_increment(&System_status_var::ha_read_rnd_count); |
| 11684 | |||
| 11685 |
3/6✓ Branch 0 taken 957703 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 957705 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 957704 times.
|
957704 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 11686 | |||
| 11687 | /* Note that we assume the length of the row reference is fixed | ||
| 11688 | for the table, and it is == ref_length */ | ||
| 11689 | |||
| 11690 |
1/2✓ Branch 0 taken 957705 times.
✗ Branch 1 not taken.
|
957704 | int error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT); |
| 11691 | |||
| 11692 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 957626 times.
|
957705 | if (error != 0) { |
| 11693 |
3/8✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 79 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
79 | DBUG_PRINT("error", ("Got error: %d", error)); |
| 11694 | } else { | ||
| 11695 | 957626 | m_start_of_scan = false; | |
| 11696 | } | ||
| 11697 | |||
| 11698 | 957705 | return error; | |
| 11699 | 957705 | } | |
| 11700 | |||
| 11701 | /** Initialize FT index scan | ||
| 11702 | @return 0 or error number */ | ||
| 11703 | |||
| 11704 | 1916 | int ha_innobase::ft_init() { | |
| 11705 |
1/2✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
|
1916 | DBUG_TRACE; |
| 11706 | |||
| 11707 |
2/4✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1916 times.
✗ Branch 3 not taken.
|
1916 | trx_t *trx = check_trx_exists(ha_thd()); |
| 11708 | |||
| 11709 | /* FTS queries are not treated as autocommit non-locking selects. | ||
| 11710 | This is because the FTS implementation can acquire locks behind | ||
| 11711 | the scenes. This has not been verified but it is safer to treat | ||
| 11712 | them as regular read only transactions for now. */ | ||
| 11713 | |||
| 11714 |
3/4✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1715 times.
✓ Branch 3 taken 201 times.
|
1916 | if (!trx_is_started(trx)) { |
| 11715 | 1715 | ++trx->will_lock; | |
| 11716 | } | ||
| 11717 | |||
| 11718 |
1/2✓ Branch 0 taken 1916 times.
✗ Branch 1 not taken.
|
3832 | return rnd_init(false); |
| 11719 | 1916 | } | |
| 11720 | |||
| 11721 | /** Initialize FT index scan | ||
| 11722 | @return FT_INFO structure if successful or NULL */ | ||
| 11723 | |||
| 11724 | 2290 | FT_INFO *ha_innobase::ft_init_ext(uint flags, /* in: */ | |
| 11725 | uint keynr, /* in: */ | ||
| 11726 | String *key) /* in: */ | ||
| 11727 | { | ||
| 11728 | 2290 | NEW_FT_INFO *fts_hdl = nullptr; | |
| 11729 | dict_index_t *index; | ||
| 11730 | fts_result_t *result; | ||
| 11731 | char buf_tmp[8192]; | ||
| 11732 | ulint buf_tmp_used; | ||
| 11733 | uint num_errors; | ||
| 11734 | 2290 | ulint query_len = key->length(); | |
| 11735 | 2290 | const CHARSET_INFO *char_set = key->charset(); | |
| 11736 | 2290 | const char *query = key->ptr(); | |
| 11737 | |||
| 11738 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2252 times.
|
2290 | if (fts_enable_diag_print) { |
| 11739 | { | ||
| 11740 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | ib::info out(ER_IB_MSG_1220); |
| 11741 |
3/6✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
|
38 | out << "keynr=" << keynr << ", '"; |
| 11742 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | out.write(key->ptr(), key->length()); |
| 11743 | 38 | } | |
| 11744 | |||
| 11745 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6 times.
|
38 | if (flags & FT_BOOL) { |
| 11746 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
|
32 | ib::info(ER_IB_MSG_562) << "BOOL search"; |
| 11747 | } else { | ||
| 11748 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | ib::info(ER_IB_MSG_563) << "NL search"; |
| 11749 | } | ||
| 11750 | } | ||
| 11751 | |||
| 11752 | /* FIXME: utf32 and utf16 are not compatible with some | ||
| 11753 | string function used. So to convert them to uft8 before | ||
| 11754 | we proceed. */ | ||
| 11755 |
1/2✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
|
2290 | if (strcmp(char_set->csname, "utf32") == 0 || |
| 11756 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2290 times.
|
2290 | strcmp(char_set->csname, "utf16") == 0) { |
| 11757 | ✗ | buf_tmp_used = innobase_convert_string( | |
| 11758 | buf_tmp, sizeof(buf_tmp) - 1, &my_charset_utf8_general_ci, query, | ||
| 11759 | query_len, (CHARSET_INFO *)char_set, &num_errors); | ||
| 11760 | |||
| 11761 | ✗ | buf_tmp[buf_tmp_used] = 0; | |
| 11762 | ✗ | query = buf_tmp; | |
| 11763 | ✗ | query_len = buf_tmp_used; | |
| 11764 | } | ||
| 11765 | |||
| 11766 | 2290 | trx_t *trx = m_prebuilt->trx; | |
| 11767 | |||
| 11768 |
1/2✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
|
2290 | TrxInInnoDB trx_in_innodb(trx); |
| 11769 | |||
| 11770 |
2/4✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2290 times.
|
2290 | if (trx_in_innodb.is_aborted()) { |
| 11771 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 11772 | |||
| 11773 | int err; | ||
| 11774 | ✗ | err = convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 11775 | |||
| 11776 | ✗ | my_error(err, MYF(0)); | |
| 11777 | |||
| 11778 | ✗ | return (nullptr); | |
| 11779 | } | ||
| 11780 | |||
| 11781 | /* FTS queries are not treated as autocommit non-locking selects. | ||
| 11782 | This is because the FTS implementation can acquire locks behind | ||
| 11783 | the scenes. This has not been verified but it is safer to treat | ||
| 11784 | them as regular read only transactions for now. */ | ||
| 11785 | |||
| 11786 |
3/4✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2118 times.
✓ Branch 3 taken 172 times.
|
2290 | if (!trx_is_started(trx)) { |
| 11787 | 2118 | ++trx->will_lock; | |
| 11788 | } | ||
| 11789 | |||
| 11790 | 2290 | dict_table_t *ft_table = m_prebuilt->table; | |
| 11791 | |||
| 11792 | /* Table does not have an FTS index */ | ||
| 11793 |
3/6✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2290 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2290 times.
|
2290 | if (!ft_table->fts || ib_vector_is_empty(ft_table->fts->indexes)) { |
| 11794 | ✗ | my_error(ER_TABLE_HAS_NO_FT, MYF(0)); | |
| 11795 | ✗ | return (nullptr); | |
| 11796 | } | ||
| 11797 | |||
| 11798 | /* If tablespace is discarded, we should return here */ | ||
| 11799 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2290 times.
|
2290 | if (dict_table_is_discarded(ft_table)) { |
| 11800 | ✗ | my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->db.str, | |
| 11801 | ✗ | table->s->table_name.str); | |
| 11802 | ✗ | return (nullptr); | |
| 11803 | } | ||
| 11804 | |||
| 11805 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2290 times.
|
2290 | if (keynr == NO_SUCH_KEY) { |
| 11806 | /* FIXME: Investigate the NO_SUCH_KEY usage */ | ||
| 11807 | ✗ | index = reinterpret_cast<dict_index_t *>( | |
| 11808 | ✗ | ib_vector_getp(ft_table->fts->indexes, 0)); | |
| 11809 | } else { | ||
| 11810 |
1/2✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
|
2290 | index = innobase_get_index(keynr); |
| 11811 | } | ||
| 11812 | |||
| 11813 |
3/4✓ Branch 0 taken 2290 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2289 times.
|
2290 | if (index == nullptr || index->type != DICT_FTS) { |
| 11814 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(ER_TABLE_HAS_NO_FT, MYF(0)); |
| 11815 | 1 | return (nullptr); | |
| 11816 | } | ||
| 11817 | |||
| 11818 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 2235 times.
|
2289 | if (!(ft_table->fts->fts_status & ADDED_TABLE_SYNCED)) { |
| 11819 |
1/2✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
|
54 | fts_init_index(ft_table, false); |
| 11820 | |||
| 11821 | 54 | ft_table->fts->fts_status |= ADDED_TABLE_SYNCED; | |
| 11822 | } | ||
| 11823 | |||
| 11824 | 2289 | const byte *q = reinterpret_cast<const byte *>(const_cast<char *>(query)); | |
| 11825 | |||
| 11826 | 4578 | dberr_t error = fts_query(trx, index, flags, q, query_len, &result, | |
| 11827 |
1/2✓ Branch 0 taken 2289 times.
✗ Branch 1 not taken.
|
2289 | m_prebuilt->m_fts_limit); |
| 11828 | |||
| 11829 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2283 times.
|
2289 | if (error != DB_SUCCESS) { |
| 11830 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | my_error(convert_error_code_to_mysql(error, 0, nullptr), MYF(0)); |
| 11831 | 6 | return (nullptr); | |
| 11832 | } | ||
| 11833 | |||
| 11834 | /* Allocate FTS handler, and instantiate it before return */ | ||
| 11835 | fts_hdl = reinterpret_cast<NEW_FT_INFO *>( | ||
| 11836 |
1/2✓ Branch 0 taken 2283 times.
✗ Branch 1 not taken.
|
2283 | my_malloc(PSI_INSTRUMENT_ME, sizeof(NEW_FT_INFO), MYF(0))); |
| 11837 | |||
| 11838 | 2283 | fts_hdl->please = const_cast<_ft_vft *>(&ft_vft_result); | |
| 11839 | 2283 | fts_hdl->could_you = const_cast<_ft_vft_ext *>(&ft_vft_ext_result); | |
| 11840 | 2283 | fts_hdl->ft_prebuilt = m_prebuilt; | |
| 11841 | 2283 | fts_hdl->ft_result = result; | |
| 11842 | |||
| 11843 | /* FIXME: Re-evaluate the condition when Bug 14469540 is resolved */ | ||
| 11844 | 2283 | m_prebuilt->in_fts_query = true; | |
| 11845 | |||
| 11846 | 2283 | return (reinterpret_cast<FT_INFO *>(fts_hdl)); | |
| 11847 | 2290 | } | |
| 11848 | |||
| 11849 | /** Initialize FT index scan | ||
| 11850 | @return FT_INFO structure if successful or NULL */ | ||
| 11851 | |||
| 11852 | 2290 | FT_INFO *ha_innobase::ft_init_ext_with_hints(uint keynr, /* in: key num */ | |
| 11853 | String *key, /* in: key */ | ||
| 11854 | Ft_hints *hints) /* in: hints */ | ||
| 11855 | { | ||
| 11856 | /* TODO Implement function properly working with FT hint. */ | ||
| 11857 |
2/2✓ Branch 0 taken 1273 times.
✓ Branch 1 taken 1017 times.
|
2290 | if (hints->get_flags() & FT_NO_RANKING) { |
| 11858 | 1273 | m_prebuilt->m_fts_limit = hints->get_limit(); | |
| 11859 | } else { | ||
| 11860 | 1017 | m_prebuilt->m_fts_limit = ULONG_UNDEFINED; | |
| 11861 | } | ||
| 11862 | |||
| 11863 | 2290 | return (ft_init_ext(hints->get_flags(), keynr, key)); | |
| 11864 | } | ||
| 11865 | |||
| 11866 | /** Set up search tuple for a query through FTS_DOC_ID_INDEX on | ||
| 11867 | supplied Doc ID. This is used by MySQL to retrieve the documents | ||
| 11868 | once the search result (Doc IDs) is available */ | ||
| 11869 | 2686 | static void innobase_fts_create_doc_id_key( | |
| 11870 | dtuple_t *tuple, /* in/out: m_prebuilt->search_tuple */ | ||
| 11871 | const dict_index_t *index, /* in: index (FTS_DOC_ID_INDEX) */ | ||
| 11872 | doc_id_t *doc_id) /* in/out: doc id to search, value | ||
| 11873 | could be changed to storage format | ||
| 11874 | used for search. */ | ||
| 11875 | { | ||
| 11876 | doc_id_t temp_doc_id; | ||
| 11877 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | dfield_t *dfield = dtuple_get_nth_field(tuple, 0); |
| 11878 | |||
| 11879 |
2/4✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2686 times.
|
2686 | ut_a(dict_index_get_n_unique(index) == 1); |
| 11880 | |||
| 11881 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | dtuple_set_n_fields(tuple, index->n_fields); |
| 11882 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | dict_index_copy_types(tuple, index, index->n_fields); |
| 11883 | |||
| 11884 | #ifdef UNIV_DEBUG | ||
| 11885 | /* The unique Doc ID field should be an eight-bytes integer */ | ||
| 11886 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | dict_field_t *field = index->get_field(0); |
| 11887 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
|
2686 | ut_a(field->col->mtype == DATA_INT); |
| 11888 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
|
2686 | ut_ad(sizeof(*doc_id) == field->fixed_len); |
| 11889 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
|
2686 | ut_ad(!strcmp(index->name, FTS_DOC_ID_INDEX_NAME)); |
| 11890 | #endif /* UNIV_DEBUG */ | ||
| 11891 | |||
| 11892 | /* Convert to storage byte order */ | ||
| 11893 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | mach_write_to_8(reinterpret_cast<byte *>(&temp_doc_id), *doc_id); |
| 11894 | 2686 | *doc_id = temp_doc_id; | |
| 11895 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | dfield_set_data(dfield, doc_id, sizeof(*doc_id)); |
| 11896 | |||
| 11897 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | dtuple_set_n_fields_cmp(tuple, 1); |
| 11898 | |||
| 11899 |
2/2✓ Branch 0 taken 2407 times.
✓ Branch 1 taken 2686 times.
|
5093 | for (ulint i = 1; i < index->n_fields; i++) { |
| 11900 |
1/2✓ Branch 0 taken 2407 times.
✗ Branch 1 not taken.
|
2407 | dfield = dtuple_get_nth_field(tuple, i); |
| 11901 |
1/2✓ Branch 0 taken 2407 times.
✗ Branch 1 not taken.
|
2407 | dfield_set_null(dfield); |
| 11902 | } | ||
| 11903 | 2686 | } | |
| 11904 | |||
| 11905 | /** Fetch next result from the FT result set | ||
| 11906 | @return error code */ | ||
| 11907 | |||
| 11908 | 4678 | int ha_innobase::ft_read(uchar *buf) /*!< in/out: buf contain result row */ | |
| 11909 | { | ||
| 11910 |
1/2✓ Branch 0 taken 4678 times.
✗ Branch 1 not taken.
|
4678 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 11911 | |||
| 11912 |
2/4✓ Branch 0 taken 4678 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4678 times.
|
4678 | if (trx_in_innodb.is_aborted()) { |
| 11913 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 11914 | |||
| 11915 | ✗ | return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd)); | |
| 11916 | } | ||
| 11917 | |||
| 11918 | row_prebuilt_t *ft_prebuilt; | ||
| 11919 | |||
| 11920 | 4678 | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_prebuilt; | |
| 11921 | |||
| 11922 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4678 times.
|
4678 | ut_a(ft_prebuilt == m_prebuilt); |
| 11923 | |||
| 11924 | fts_result_t *result; | ||
| 11925 | |||
| 11926 | 4678 | result = reinterpret_cast<NEW_FT_INFO *>(ft_handler)->ft_result; | |
| 11927 | |||
| 11928 |
2/2✓ Branch 0 taken 1914 times.
✓ Branch 1 taken 2764 times.
|
4678 | if (result->current == nullptr) { |
| 11929 | /* This is the case where the FTS query did not | ||
| 11930 | contain and matching documents. */ | ||
| 11931 |
2/2✓ Branch 0 taken 1431 times.
✓ Branch 1 taken 483 times.
|
1914 | if (result->rankings_by_id != nullptr) { |
| 11932 | /* Now that we have the complete result, we | ||
| 11933 | need to sort the document ids on their rank | ||
| 11934 | calculation. */ | ||
| 11935 | |||
| 11936 |
1/2✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
|
1431 | fts_query_sort_result_on_rank(result); |
| 11937 | |||
| 11938 | 1431 | result->current = | |
| 11939 |
1/2✓ Branch 0 taken 1431 times.
✗ Branch 1 not taken.
|
1431 | const_cast<ib_rbt_node_t *>(rbt_first(result->rankings_by_rank)); |
| 11940 | } else { | ||
| 11941 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 483 times.
|
483 | ut_a(result->current == nullptr); |
| 11942 | } | ||
| 11943 | } else { | ||
| 11944 | 2764 | result->current = const_cast<ib_rbt_node_t *>( | |
| 11945 |
1/2✓ Branch 0 taken 2764 times.
✗ Branch 1 not taken.
|
2764 | rbt_next(result->rankings_by_rank, result->current)); |
| 11946 | } | ||
| 11947 | |||
| 11948 | 4678 | next_record: | |
| 11949 | |||
| 11950 |
2/2✓ Branch 0 taken 2820 times.
✓ Branch 1 taken 1862 times.
|
4682 | if (result->current != nullptr) { |
| 11951 | doc_id_t search_doc_id; | ||
| 11952 | 2820 | dtuple_t *tuple = m_prebuilt->search_tuple; | |
| 11953 | |||
| 11954 | /* If we only need information from result we can return | ||
| 11955 | without fetching the table row */ | ||
| 11956 |
2/2✓ Branch 0 taken 134 times.
✓ Branch 1 taken 2686 times.
|
2820 | if (ft_prebuilt->read_just_key) { |
| 11957 | 134 | const fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 11958 | 134 | m_prebuilt->fts_doc_id = ranking->doc_id; | |
| 11959 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | if (m_prebuilt->fts_doc_id_in_read_set) { |
| 11960 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | innobase_fts_store_docid(table, ranking->doc_id); |
| 11961 | } | ||
| 11962 | 2816 | return (0); | |
| 11963 | } | ||
| 11964 | |||
| 11965 | dict_index_t *index; | ||
| 11966 | |||
| 11967 | 2686 | index = m_prebuilt->table->fts_doc_id_index; | |
| 11968 | |||
| 11969 | /* Must find the index */ | ||
| 11970 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2686 times.
|
2686 | ut_a(index != nullptr); |
| 11971 | |||
| 11972 | /* Switch to the FTS doc id index */ | ||
| 11973 | 2686 | m_prebuilt->index = index; | |
| 11974 | |||
| 11975 | 2686 | fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 11976 | |||
| 11977 | 2686 | search_doc_id = ranking->doc_id; | |
| 11978 | |||
| 11979 | /* We pass a pointer of search_doc_id because it will be | ||
| 11980 | converted to storage byte order used in the search | ||
| 11981 | tuple. */ | ||
| 11982 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | innobase_fts_create_doc_id_key(tuple, index, &search_doc_id); |
| 11983 | |||
| 11984 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | auto ret = innobase_srv_conc_enter_innodb(m_prebuilt); |
| 11985 | |||
| 11986 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | if (ret == DB_SUCCESS) { |
| 11987 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | ret = row_search_for_mysql((byte *)buf, PAGE_CUR_GE, m_prebuilt, |
| 11988 | ROW_SEL_EXACT, 0); | ||
| 11989 |
1/2✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
|
2686 | innobase_srv_conc_exit_innodb(m_prebuilt); |
| 11990 | } | ||
| 11991 | |||
| 11992 | int error; | ||
| 11993 | |||
| 11994 |
6/14✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2686 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2686 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2686 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2686 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2686 times.
|
2686 | if (UNIV_UNLIKELY(srv_pass_corrupt_table <= 1 && m_share && |
| 11995 | m_share->ib_table && m_share->ib_table->is_corrupt)) { | ||
| 11996 | ✗ | return (HA_ERR_CRASHED); | |
| 11997 | } | ||
| 11998 | |||
| 11999 |
2/6✓ Branch 0 taken 2670 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
2686 | switch (ret) { |
| 12000 | 2670 | case DB_SUCCESS: | |
| 12001 | 2670 | error = 0; | |
| 12002 | 2670 | break; | |
| 12003 | 16 | case DB_RECORD_NOT_FOUND: | |
| 12004 | 16 | result->current = const_cast<ib_rbt_node_t *>( | |
| 12005 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | rbt_next(result->rankings_by_rank, result->current)); |
| 12006 | |||
| 12007 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | if (!result->current) { |
| 12008 | /* exhaust the result set, should return | ||
| 12009 | HA_ERR_END_OF_FILE just like | ||
| 12010 | ha_innobase::general_fetch() and/or | ||
| 12011 | ha_innobase::index_first() etc. */ | ||
| 12012 | 12 | error = HA_ERR_END_OF_FILE; | |
| 12013 | } else { | ||
| 12014 | 4 | goto next_record; | |
| 12015 | } | ||
| 12016 | 12 | break; | |
| 12017 | ✗ | case DB_END_OF_INDEX: | |
| 12018 | ✗ | error = HA_ERR_END_OF_FILE; | |
| 12019 | ✗ | break; | |
| 12020 | ✗ | case DB_TABLESPACE_DELETED: | |
| 12021 | |||
| 12022 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 12023 | ✗ | ER_TABLESPACE_DISCARDED, table->s->table_name.str); | |
| 12024 | |||
| 12025 | ✗ | error = HA_ERR_NO_SUCH_TABLE; | |
| 12026 | ✗ | break; | |
| 12027 | ✗ | case DB_TABLESPACE_NOT_FOUND: | |
| 12028 | |||
| 12029 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 12030 | ✗ | ER_TABLESPACE_MISSING, table->s->table_name.str); | |
| 12031 | |||
| 12032 | ✗ | error = HA_ERR_TABLESPACE_MISSING; | |
| 12033 | ✗ | break; | |
| 12034 | ✗ | default: | |
| 12035 | ✗ | error = convert_error_code_to_mysql(ret, 0, m_user_thd); | |
| 12036 | |||
| 12037 | ✗ | break; | |
| 12038 | } | ||
| 12039 | |||
| 12040 | 2682 | return (error); | |
| 12041 | } | ||
| 12042 | |||
| 12043 | 1862 | return (HA_ERR_END_OF_FILE); | |
| 12044 | 4678 | } | |
| 12045 | |||
| 12046 | /************************************************************************* | ||
| 12047 | */ | ||
| 12048 | |||
| 12049 | ✗ | void ha_innobase::ft_end() { | |
| 12050 | ✗ | ib::info(ER_IB_MSG_564) << "ft_end()"; | |
| 12051 | |||
| 12052 | ✗ | rnd_end(); | |
| 12053 | } | ||
| 12054 | |||
| 12055 | /** | ||
| 12056 | Store a reference to the current row to 'ref' field of the handle. | ||
| 12057 | Note that in the case where we have generated the clustered index for the | ||
| 12058 | table, the function parameter is illogical: we MUST ASSUME that 'record' | ||
| 12059 | is the current 'position' of the handle, because if row ref is actually | ||
| 12060 | the row id internally generated in InnoDB, then 'record' does not contain | ||
| 12061 | it. We just guess that the row id must be for the record where the handle | ||
| 12062 | was positioned the last time. | ||
| 12063 | @param[in] record row in MySQL format */ | ||
| 12064 | 1240446 | void ha_innobase::position(const uchar *record) { | |
| 12065 | uint len; | ||
| 12066 | |||
| 12067 |
1/2✓ Branch 0 taken 1240446 times.
✗ Branch 1 not taken.
|
1240446 | DBUG_TRACE; |
| 12068 |
3/6✓ Branch 0 taken 1240446 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1240446 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1240446 times.
|
1240446 | assert(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 12069 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1240446 times.
|
1240446 | assert(table_share->is_missing_primary_key() == |
| 12070 | (bool)m_prebuilt->clust_index_was_generated); | ||
| 12071 | |||
| 12072 |
2/2✓ Branch 0 taken 958874 times.
✓ Branch 1 taken 281572 times.
|
1240446 | if (m_prebuilt->clust_index_was_generated) { |
| 12073 | /* No primary key was defined for the table and we | ||
| 12074 | generated the clustered index from row id: the | ||
| 12075 | row reference will be the row id, not any key value | ||
| 12076 | that MySQL knows of */ | ||
| 12077 | |||
| 12078 | 958874 | len = DATA_ROW_ID_LEN; | |
| 12079 | |||
| 12080 | 958874 | memcpy(ref, m_prebuilt->row_id, len); | |
| 12081 | } else { | ||
| 12082 | /* Copy primary key as the row reference */ | ||
| 12083 | 281572 | KEY *key_info = table->key_info + table_share->primary_key; | |
| 12084 |
1/2✓ Branch 0 taken 281573 times.
✗ Branch 1 not taken.
|
281572 | key_copy(ref, (uchar *)record, key_info, key_info->key_length); |
| 12085 | 281573 | len = key_info->key_length; | |
| 12086 | } | ||
| 12087 | |||
| 12088 | /* We assume that the 'ref' value len is always fixed for the same | ||
| 12089 | table. */ | ||
| 12090 | |||
| 12091 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1240447 times.
|
1240447 | if (len != ref_length) { |
| 12092 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_DIFF_IN_REF_LEN, (ulong)len, | |
| 12093 | (ulong)ref_length); | ||
| 12094 | } | ||
| 12095 | 1240447 | } | |
| 12096 | |||
| 12097 | /** Set up base columns for virtual column | ||
| 12098 | @param[in] table the InnoDB table | ||
| 12099 | @param[in] field MySQL field | ||
| 12100 | @param[in,out] v_col virtual column to be set up */ | ||
| 12101 | 33429 | void innodb_base_col_setup(dict_table_t *table, const Field *field, | |
| 12102 | dict_v_col_t *v_col) { | ||
| 12103 | 33429 | int n = 0; | |
| 12104 | |||
| 12105 |
2/2✓ Branch 0 taken 531818 times.
✓ Branch 1 taken 33429 times.
|
565247 | for (uint i = 0; i < field->table->s->fields; ++i) { |
| 12106 | 531818 | const Field *base_field = field->table->field[i]; | |
| 12107 | |||
| 12108 |
6/6✓ Branch 0 taken 150711 times.
✓ Branch 1 taken 381107 times.
✓ Branch 2 taken 32845 times.
✓ Branch 3 taken 117866 times.
✓ Branch 4 taken 32845 times.
✓ Branch 5 taken 498973 times.
|
682529 | if (!base_field->is_virtual_gcol() && |
| 12109 | 150711 | bitmap_is_set(&field->gcol_info->base_columns_map, i)) { | |
| 12110 | ulint z; | ||
| 12111 | |||
| 12112 |
1/2✓ Branch 0 taken 64261 times.
✗ Branch 1 not taken.
|
64261 | for (z = 0; z < table->n_cols; z++) { |
| 12113 | 64261 | const char *name = table->get_col_name(z); | |
| 12114 |
2/2✓ Branch 0 taken 32845 times.
✓ Branch 1 taken 31416 times.
|
64261 | if (!innobase_strcasecmp(name, base_field->field_name)) { |
| 12115 | 32845 | break; | |
| 12116 | } | ||
| 12117 | } | ||
| 12118 | |||
| 12119 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32845 times.
|
32845 | ut_ad(z != table->n_cols); |
| 12120 | |||
| 12121 | 32845 | v_col->base_col[n] = table->get_col(z); | |
| 12122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32845 times.
|
32845 | ut_ad(v_col->base_col[n]->ind == z); |
| 12123 | 32845 | n++; | |
| 12124 | } | ||
| 12125 | } | ||
| 12126 | 33429 | } | |
| 12127 | |||
| 12128 | /** Set up base columns for stored column | ||
| 12129 | @param[in] table InnoDB table | ||
| 12130 | @param[in] field MySQL field | ||
| 12131 | @param[in,out] s_col stored column */ | ||
| 12132 | 2231 | void innodb_base_col_setup_for_stored(const dict_table_t *table, | |
| 12133 | const Field *field, dict_s_col_t *s_col) { | ||
| 12134 | 2231 | ulint n = 0; | |
| 12135 | |||
| 12136 |
2/2✓ Branch 0 taken 4583 times.
✓ Branch 1 taken 22 times.
|
4605 | for (uint i = 0; i < field->table->s->fields; ++i) { |
| 12137 | 4583 | const Field *base_field = field->table->field[i]; | |
| 12138 | |||
| 12139 |
8/8✓ Branch 0 taken 202 times.
✓ Branch 1 taken 4381 times.
✓ Branch 2 taken 103 times.
✓ Branch 3 taken 99 times.
✓ Branch 4 taken 2255 times.
✓ Branch 5 taken 2229 times.
✓ Branch 6 taken 2255 times.
✓ Branch 7 taken 2328 times.
|
9067 | if (!innobase_is_v_fld(base_field) && |
| 12140 | 4484 | bitmap_is_set(&field->gcol_info->base_columns_map, i)) { | |
| 12141 | ulint z; | ||
| 12142 |
1/2✓ Branch 0 taken 4566 times.
✗ Branch 1 not taken.
|
4566 | for (z = 0; z < table->n_cols; z++) { |
| 12143 | 4566 | const char *name = table->get_col_name(z); | |
| 12144 |
2/2✓ Branch 0 taken 2255 times.
✓ Branch 1 taken 2311 times.
|
4566 | if (!innobase_strcasecmp(name, base_field->field_name)) { |
| 12145 | 2255 | break; | |
| 12146 | } | ||
| 12147 | } | ||
| 12148 | |||
| 12149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2255 times.
|
2255 | ut_ad(z != table->n_cols); |
| 12150 | |||
| 12151 | 2255 | s_col->base_col[n] = table->get_col(z); | |
| 12152 | 2255 | n++; | |
| 12153 | |||
| 12154 |
2/2✓ Branch 0 taken 2209 times.
✓ Branch 1 taken 46 times.
|
2255 | if (n == s_col->num_base) { |
| 12155 | 2209 | break; | |
| 12156 | } | ||
| 12157 | } | ||
| 12158 | } | ||
| 12159 | 2231 | } | |
| 12160 | |||
| 12161 | /** If encryption is requested, check for master key availability | ||
| 12162 | and set the encryption flag in table flags | ||
| 12163 | @param[in,out] table table object | ||
| 12164 | @return on success DB_SUCCESS else DB_UNSPPORTED on failure */ | ||
| 12165 | 4278 | dberr_t create_table_info_t::enable_master_key_encryption(dict_table_t *table) { | |
| 12166 | 4278 | const char *encrypt = m_create_info->encrypt_type.str; | |
| 12167 | |||
| 12168 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4278 times.
|
4278 | if (Encryption::is_none(encrypt)) return (DB_SUCCESS); |
| 12169 | |||
| 12170 | /* If table is part of tablespace - no need for retrieving | ||
| 12171 | master key as tablespace key was already decrypted | ||
| 12172 | either by validate_first_page or during tablespace creation. | ||
| 12173 | Just set the encryption flag and return. */ | ||
| 12174 |
2/2✓ Branch 0 taken 791 times.
✓ Branch 1 taken 3487 times.
|
4278 | if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE)) { |
| 12175 | 791 | DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE); | |
| 12176 | 791 | return (DB_SUCCESS); | |
| 12177 | } | ||
| 12178 | |||
| 12179 | /* Set the encryption flag. */ | ||
| 12180 | 3487 | byte *master_key = nullptr; | |
| 12181 | uint32_t master_key_id; | ||
| 12182 | |||
| 12183 | /* Check if keyring is ready. */ | ||
| 12184 | 3487 | Encryption::get_master_key(&master_key_id, &master_key); | |
| 12185 | |||
| 12186 | 3487 | dberr_t err = DB_SUCCESS; | |
| 12187 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 3302 times.
|
3487 | if (master_key == nullptr) { |
| 12188 |
1/2✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
|
185 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 12189 | 185 | err = DB_UNSUPPORTED; | |
| 12190 | } else { | ||
| 12191 |
1/2✓ Branch 0 taken 3302 times.
✗ Branch 1 not taken.
|
3302 | my_free(master_key); |
| 12192 | 3302 | DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE); | |
| 12193 | } | ||
| 12194 | |||
| 12195 | 3487 | return (err); | |
| 12196 | } | ||
| 12197 | |||
| 12198 | /** Retrive keyring encryption mode | ||
| 12199 | @param[in] encrypt_type from ENCRYPTION clause | ||
| 12200 | @param[in] explicit_encryption was ENCRYPTION clause used | ||
| 12201 | @param[in] flags tabelspace flags | ||
| 12202 | @retval FIL_ENCRYPTION_OFF tablespace should be skipped by | ||
| 12203 | encryption threads | ||
| 12204 | FIL_ENCRYPTION_DEFAULT online encryption allowed by | ||
| 12205 | encryption threads | ||
| 12206 | FIL_ENCRYPTION_ON table should be keyring encrypted */ | ||
| 12207 | 410425 | static fil_encryption_t get_encryption_mode(const char *encrypt_type, | |
| 12208 | bool explicit_encryption) { | ||
| 12209 |
6/6✓ Branch 0 taken 586 times.
✓ Branch 1 taken 409839 times.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 345 times.
✓ Branch 4 taken 241 times.
✓ Branch 5 taken 410184 times.
|
410425 | if (explicit_encryption && innobase_strcasecmp(encrypt_type, "n") == 0) { |
| 12210 | 241 | return FIL_ENCRYPTION_OFF; | |
| 12211 | } | ||
| 12212 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 410107 times.
|
410184 | if (Encryption::is_keyring(encrypt_type)) { |
| 12213 | 77 | return FIL_ENCRYPTION_ON; | |
| 12214 | } | ||
| 12215 | 410107 | return FIL_ENCRYPTION_DEFAULT; | |
| 12216 | } | ||
| 12217 | |||
| 12218 | 85 | dberr_t create_table_info_t::check_tablespace_key( | |
| 12219 | const EncryptionKeyId encryption_key_id) { | ||
| 12220 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
|
85 | if (!Encryption::tablespace_key_exists_or_create_new_one_if_does_not_exist( |
| 12221 | encryption_key_id, server_uuid)) { | ||
| 12222 | ✗ | my_printf_error( | |
| 12223 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 12224 | "Seems that keyring is down. It is not possible to create encrypted " | ||
| 12225 | "tables " | ||
| 12226 | " without keyring. Please install a keyring and try again.", | ||
| 12227 | MYF(0)); | ||
| 12228 | ✗ | return (DB_UNSUPPORTED); | |
| 12229 | } | ||
| 12230 | 85 | return DB_SUCCESS; | |
| 12231 | } | ||
| 12232 | |||
| 12233 | /** Enable keyring encryption for table | ||
| 12234 | @param[in,out] table table to have its encryption flag set | ||
| 12235 | in case it should be KEYRING encrypted | ||
| 12236 | @param[out] keyring_encryption_mode FIL_ENCRYPTION_ON | | ||
| 12237 | FIL_ENCRYPTION_OFF | FIL_ENCRYPTION_DEFAULT | ||
| 12238 | @retval DB_UNSUPPORTED on error | ||
| 12239 | DB_SUCCESS on success */ | ||
| 12240 | 409537 | dberr_t create_table_info_t::enable_keyring_encryption( | |
| 12241 | dict_table_t *table, fil_encryption_t &keyring_encryption_mode) { | ||
| 12242 | 409537 | keyring_encryption_mode = | |
| 12243 | 819074 | get_encryption_mode(m_create_info->encrypt_type.str, | |
| 12244 | 409537 | m_create_info->used_fields & HA_CREATE_USED_ENCRYPT); | |
| 12245 | |||
| 12246 |
2/2✓ Branch 0 taken 409460 times.
✓ Branch 1 taken 77 times.
|
818997 | bool is_encrypted = keyring_encryption_mode == FIL_ENCRYPTION_ON || |
| 12247 |
3/4✓ Branch 0 taken 409460 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 409452 times.
|
818920 | (keyring_encryption_mode == FIL_ENCRYPTION_DEFAULT && |
| 12248 | 409460 | Encryption::is_online_encryption_on()); | |
| 12249 | |||
| 12250 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 409452 times.
|
409537 | if (is_encrypted) |
| 12251 | 85 | DICT_TF2_FLAG_SET(table, DICT_TF2_ENCRYPTION_FILE_PER_TABLE); | |
| 12252 | |||
| 12253 |
3/4✓ Branch 0 taken 409452 times.
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 409452 times.
|
409537 | if (is_encrypted || m_create_info->was_encryption_key_id_set) |
| 12254 | 85 | return check_tablespace_key(m_create_info->encryption_key_id); | |
| 12255 | |||
| 12256 | 409452 | return DB_SUCCESS; | |
| 12257 | } | ||
| 12258 | |||
| 12259 | /** Create a table definition to an InnoDB database. | ||
| 12260 | @param[in] dd_table dd::Table or nullptr for intrinsic table | ||
| 12261 | @param[in] old_part_table dd::Table from an old partition for partitioned | ||
| 12262 | table, NULL otherwise. | ||
| 12263 | @return HA_* level error */ | ||
| 12264 | 429473 | [[nodiscard]] inline int create_table_info_t::create_table_def( | |
| 12265 | const dd::Table *dd_table, const dd::Table *old_part_table) { | ||
| 12266 | dict_table_t *table; | ||
| 12267 | ulint n_cols; | ||
| 12268 | 429473 | dberr_t err = DB_SUCCESS; | |
| 12269 | ulint col_type; | ||
| 12270 | ulint col_len; | ||
| 12271 | ulint compressed; | ||
| 12272 | ulint i; | ||
| 12273 | 429473 | ulint j = 0; | |
| 12274 | 429473 | ulint doc_id_col = 0; | |
| 12275 | 429473 | bool has_doc_id_col = false; | |
| 12276 | mem_heap_t *heap; | ||
| 12277 | 429473 | ulint num_v = 0; | |
| 12278 | 429473 | ulint num_m_v = 0; | |
| 12279 | 429473 | space_id_t space_id = 0; | |
| 12280 | 429473 | dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID; | |
| 12281 | ulint actual_n_cols; | ||
| 12282 | |||
| 12283 | fil_encryption_t keyring_encryption_option = | ||
| 12284 | 429473 | Encryption::none_explicitly_specified(m_create_info->explicit_encryption, | |
| 12285 | 429473 | m_create_info->encrypt_type.str) | |
| 12286 |
2/2✓ Branch 0 taken 15629 times.
✓ Branch 1 taken 413845 times.
|
429474 | ? FIL_ENCRYPTION_OFF |
| 12287 | 429474 | : FIL_ENCRYPTION_DEFAULT; | |
| 12288 | |||
| 12289 | 429474 | uint32_t i_c = 0; | |
| 12290 | 429474 | uint32_t c_c = 0; | |
| 12291 | 429474 | uint32_t t_c = 0; | |
| 12292 | 429474 | uint32_t c_r_v = 0; | |
| 12293 | |||
| 12294 |
1/2✓ Branch 0 taken 429474 times.
✗ Branch 1 not taken.
|
429474 | DBUG_TRACE; |
| 12295 |
5/8✓ Branch 0 taken 429474 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 429473 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 429465 times.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
|
429474 | DBUG_PRINT("enter", ("table_name: %s", m_table_name)); |
| 12296 | |||
| 12297 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 429473 times.
|
429473 | assert(m_trx->mysql_thd == m_thd); |
| 12298 | |||
| 12299 | bool part_table_with_instant_cols = | ||
| 12300 |
5/6✓ Branch 0 taken 85 times.
✓ Branch 1 taken 429388 times.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 12 times.
|
429473 | (old_part_table != nullptr && dd_table_has_row_versions(*old_part_table)); |
| 12301 | |||
| 12302 | /* MySQL does the name length check. But we do additional check | ||
| 12303 | on the name length here */ | ||
| 12304 | 429473 | const size_t table_name_len = strlen(m_table_name); | |
| 12305 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 429473 times.
|
429473 | if (table_name_len > MAX_FULL_NAME_LEN) { |
| 12306 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME, | |
| 12307 | "InnoDB: Table Name or Database Name is too long"); | ||
| 12308 | |||
| 12309 | ✗ | return HA_ERR_WRONG_TABLE_NAME; | |
| 12310 | } | ||
| 12311 | |||
| 12312 | /* Make sure that the table name is acceptable. */ | ||
| 12313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 429473 times.
|
429473 | if (m_table_name[table_name_len - 1] == '/') { |
| 12314 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME, | |
| 12315 | "InnoDB: Table name is empty"); | ||
| 12316 | |||
| 12317 | ✗ | return HA_ERR_WRONG_TABLE_NAME; | |
| 12318 | } | ||
| 12319 | |||
| 12320 | fts_aux_table_t aux_table; | ||
| 12321 |
3/4✓ Branch 0 taken 429473 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 429447 times.
|
429473 | if (fts_is_aux_table_name(&aux_table, m_table_name, strlen(m_table_name))) { |
| 12322 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | push_warning_printf( |
| 12323 | m_thd, Sql_condition::SL_WARNING, ER_WRONG_TABLE_NAME, | ||
| 12324 | "Invalid table name. `%s` has the form of an FTS auxiliary table name", | ||
| 12325 | m_table_name); | ||
| 12326 | 26 | return HA_ERR_WRONG_TABLE_NAME; | |
| 12327 | } | ||
| 12328 | |||
| 12329 | 429447 | n_cols = m_form->s->fields; | |
| 12330 | |||
| 12331 | /* Find out any virtual column */ | ||
| 12332 |
2/2✓ Branch 0 taken 3352337 times.
✓ Branch 1 taken 429447 times.
|
3781784 | for (i = 0; i < n_cols; i++) { |
| 12333 | 3352337 | Field *field = m_form->field[i]; | |
| 12334 | |||
| 12335 |
7/10✓ Branch 0 taken 9273 times.
✓ Branch 1 taken 3343064 times.
✓ Branch 2 taken 2227 times.
✓ Branch 3 taken 7046 times.
✓ Branch 4 taken 3345291 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3345291 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3352337 times.
|
3352337 | ut_ad(!(!innobase_is_v_fld(field) && innobase_is_multi_value_fld(field))); |
| 12336 | |||
| 12337 |
4/4✓ Branch 0 taken 9273 times.
✓ Branch 1 taken 3343064 times.
✓ Branch 2 taken 7046 times.
✓ Branch 3 taken 2227 times.
|
3352337 | if (innobase_is_v_fld(field)) { |
| 12338 | 7046 | num_v++; | |
| 12339 | |||
| 12340 |
3/4✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 6808 times.
|
7046 | if (innobase_is_multi_value_fld(field)) { |
| 12341 | 238 | num_m_v++; | |
| 12342 | } | ||
| 12343 | } | ||
| 12344 | } | ||
| 12345 | |||
| 12346 | /* Check whether there already exists a FTS_DOC_ID column */ | ||
| 12347 |
3/4✓ Branch 0 taken 429447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 429408 times.
|
429447 | if (create_table_check_doc_id_col(m_trx->mysql_thd, m_form, &doc_id_col)) { |
| 12348 | /* Raise error if the Doc ID column is of wrong type or name */ | ||
| 12349 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 38 times.
|
39 | if (doc_id_col == ULINT_UNDEFINED) { |
| 12350 | 1 | err = DB_ERROR; | |
| 12351 | 1 | goto error_ret; | |
| 12352 | } else { | ||
| 12353 | 38 | has_doc_id_col = true; | |
| 12354 | } | ||
| 12355 | } | ||
| 12356 | |||
| 12357 | /* For single-table tablespaces, we pass 0 as the space id, and then | ||
| 12358 | determine the actual space id when the tablespace is created. */ | ||
| 12359 |
2/2✓ Branch 0 taken 30520 times.
✓ Branch 1 taken 398926 times.
|
429446 | if (DICT_TF_HAS_SHARED_SPACE(m_flags)) { |
| 12360 |
3/6✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30520 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30520 times.
|
30520 | ut_ad(m_tablespace != nullptr && m_tablespace[0] != '\0'); |
| 12361 | |||
| 12362 |
1/2✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
|
30520 | space_id = fil_space_get_id_by_name(m_tablespace); |
| 12363 |
2/4✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30520 times.
✗ Branch 3 not taken.
|
30520 | dd_space_id = (dd_table != nullptr ? dd_table->tablespace_id() |
| 12364 | : dd::INVALID_OBJECT_ID); | ||
| 12365 | } | ||
| 12366 | |||
| 12367 | /* Adjust the number of columns for the FTS hidden field */ | ||
| 12368 | 429446 | actual_n_cols = n_cols; | |
| 12369 |
4/4✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428853 times.
✓ Branch 2 taken 573 times.
✓ Branch 3 taken 20 times.
|
429446 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) { |
| 12370 | 573 | actual_n_cols += 1; | |
| 12371 | } | ||
| 12372 | |||
| 12373 |
2/2✓ Branch 0 taken 73 times.
✓ Branch 1 taken 429373 times.
|
429446 | if (part_table_with_instant_cols) { |
| 12374 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | dd_table_get_column_counters(*old_part_table, i_c, c_c, t_c, c_r_v); |
| 12375 | } | ||
| 12376 | |||
| 12377 |
1/2✓ Branch 0 taken 429447 times.
✗ Branch 1 not taken.
|
429446 | table = dict_mem_table_create(m_table_name, space_id, actual_n_cols, num_v, |
| 12378 | num_m_v, m_flags, m_flags2, t_c - c_c); | ||
| 12379 | |||
| 12380 | /* Set dd tablespace id */ | ||
| 12381 | 429447 | table->dd_space_id = dd_space_id; | |
| 12382 | |||
| 12383 | /* Set the hidden doc_id column. */ | ||
| 12384 |
2/2✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428854 times.
|
429447 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) { |
| 12385 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 573 times.
|
593 | table->fts->doc_col = has_doc_id_col ? doc_id_col : n_cols - num_v; |
| 12386 | } | ||
| 12387 | |||
| 12388 |
2/2✓ Branch 0 taken 435 times.
✓ Branch 1 taken 429011 times.
|
429447 | if (DICT_TF_HAS_DATA_DIR(m_flags)) { |
| 12389 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 435 times.
|
435 | ut_a(strlen(m_remote_path) != 0); |
| 12390 | |||
| 12391 |
1/2✓ Branch 0 taken 435 times.
✗ Branch 1 not taken.
|
435 | table->data_dir_path = mem_heap_strdup(table->heap, m_remote_path); |
| 12392 | |||
| 12393 | } else { | ||
| 12394 | 429011 | table->data_dir_path = nullptr; | |
| 12395 | } | ||
| 12396 | |||
| 12397 |
2/2✓ Branch 0 taken 30520 times.
✓ Branch 1 taken 398927 times.
|
429446 | if (DICT_TF_HAS_SHARED_SPACE(m_flags)) { |
| 12398 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30520 times.
|
30520 | ut_ad(strlen(m_tablespace)); |
| 12399 |
1/2✓ Branch 0 taken 30520 times.
✗ Branch 1 not taken.
|
30520 | table->tablespace = mem_heap_strdup(table->heap, m_tablespace); |
| 12400 | } else { | ||
| 12401 | 398927 | table->tablespace = nullptr; | |
| 12402 | } | ||
| 12403 | |||
| 12404 | /* Initialize row version and column counts for new table */ | ||
| 12405 |
2/2✓ Branch 0 taken 429373 times.
✓ Branch 1 taken 73 times.
|
429446 | if (!part_table_with_instant_cols) { |
| 12406 | 429373 | table->current_row_version = 0; | |
| 12407 | 429373 | table->initial_col_count = n_cols - num_v; | |
| 12408 | 429373 | table->current_col_count = table->initial_col_count; | |
| 12409 | 429373 | table->total_col_count = table->initial_col_count; | |
| 12410 | } else { | ||
| 12411 | /* This is a new partition getting created. We need to inherit INSTANT | ||
| 12412 | instant metadata from old partition table */ | ||
| 12413 | 73 | table->initial_col_count = i_c; | |
| 12414 | 73 | table->current_col_count = c_c; | |
| 12415 | 73 | table->total_col_count = t_c; | |
| 12416 | 73 | table->current_row_version = c_r_v; | |
| 12417 | 73 | table->discard_after_ddl = true; | |
| 12418 | |||
| 12419 | #ifdef UNIV_DEBUG | ||
| 12420 | /* Get and set current row version for table */ | ||
| 12421 | 73 | uint32_t v = 0; | |
| 12422 |
6/10✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 515 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 515 times.
✓ Branch 9 taken 73 times.
|
588 | for (auto col : old_part_table->columns()) { |
| 12423 |
3/4✓ Branch 0 taken 515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 445 times.
|
515 | if (dd_column_is_dropped(col)) { |
| 12424 |
1/2✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
|
70 | uint32_t value = dd_column_get_version_dropped(col); |
| 12425 | 70 | v = std::max(v, value); | |
| 12426 | 70 | continue; | |
| 12427 | 70 | } | |
| 12428 | |||
| 12429 |
3/4✓ Branch 0 taken 445 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 333 times.
|
445 | if (dd_column_is_added(col)) { |
| 12430 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | uint32_t value = dd_column_get_version_added(col); |
| 12431 | 112 | v = std::max(v, value); | |
| 12432 | 112 | continue; | |
| 12433 | 112 | } | |
| 12434 | } | ||
| 12435 |
2/4✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
|
73 | ut_ad(dd_is_valid_row_version(v)); |
| 12436 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | ut_ad(table->current_row_version == v); |
| 12437 | #endif | ||
| 12438 | } | ||
| 12439 | |||
| 12440 |
1/2✓ Branch 0 taken 429447 times.
✗ Branch 1 not taken.
|
429446 | heap = mem_heap_create(1000, UT_LOCATION_HERE); |
| 12441 | |||
| 12442 |
2/2✓ Branch 0 taken 3352330 times.
✓ Branch 1 taken 429444 times.
|
3781774 | for (i = 0; i < n_cols; i++) { |
| 12443 | ulint nulls_allowed; | ||
| 12444 | ulint unsigned_type; | ||
| 12445 | ulint binary_type; | ||
| 12446 | ulint long_true_varchar; | ||
| 12447 | ulint charset_no; | ||
| 12448 | ulint is_virtual; | ||
| 12449 | ulint is_multi_val; | ||
| 12450 | 3352330 | bool is_stored = false; | |
| 12451 | |||
| 12452 | 3352330 | Field *field = m_form->field[i]; | |
| 12453 | |||
| 12454 | /* Generate a unique column name by pre-pending table-name for | ||
| 12455 | intrinsic tables. For other tables (including normal | ||
| 12456 | temporary) column names are unique. If not, MySQL layer will | ||
| 12457 | block such statement. | ||
| 12458 | This is work-around fix till Optimizer can handle this issue | ||
| 12459 | (probably 5.7.4+). */ | ||
| 12460 | char field_name[MAX_FULL_NAME_LEN + 2 + 10]; | ||
| 12461 | |||
| 12462 |
6/8✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2605781 times.
✓ Branch 3 taken 746549 times.
✓ Branch 4 taken 2605781 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2605781 times.
✓ Branch 7 taken 746549 times.
|
3352330 | if (table->is_intrinsic() && field->table) { |
| 12463 | 2605781 | snprintf(field_name, sizeof(field_name), "%s_%s_" ULINTPF, | |
| 12464 | 2605781 | field->table->alias, field->field_name, i); | |
| 12465 | |||
| 12466 | } else { | ||
| 12467 | 746549 | snprintf(field_name, sizeof(field_name), "%s", field->field_name); | |
| 12468 | } | ||
| 12469 | |||
| 12470 |
1/2✓ Branch 0 taken 3352331 times.
✗ Branch 1 not taken.
|
3352330 | col_type = get_innobase_type_from_mysql_type(&unsigned_type, field); |
| 12471 | |||
| 12472 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3352331 times.
|
3352331 | if (!col_type) { |
| 12473 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 12474 | ER_CANT_CREATE_TABLE, | ||
| 12475 | "Error creating table '%s' with" | ||
| 12476 | " column '%s'. Please check its" | ||
| 12477 | " column type and try to re-create" | ||
| 12478 | " the table with an appropriate" | ||
| 12479 | " column type.", | ||
| 12480 | table->name.m_name, field->field_name); | ||
| 12481 | ✗ | goto err_col; | |
| 12482 | } | ||
| 12483 | |||
| 12484 |
2/2✓ Branch 0 taken 1220668 times.
✓ Branch 1 taken 2131663 times.
|
3352331 | nulls_allowed = field->is_nullable() ? 0 : DATA_NOT_NULL; |
| 12485 |
3/4✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1710953 times.
✓ Branch 3 taken 1641377 times.
|
3352331 | binary_type = field->binary() ? DATA_BINARY_TYPE : 0; |
| 12486 | |||
| 12487 | 3352330 | charset_no = 0; | |
| 12488 | |||
| 12489 |
3/4✓ Branch 0 taken 3352331 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1712989 times.
✓ Branch 3 taken 1639342 times.
|
3352330 | if (dtype_is_string_type(col_type)) { |
| 12490 |
1/2✓ Branch 0 taken 1712989 times.
✗ Branch 1 not taken.
|
1712989 | charset_no = (ulint)field->charset()->number; |
| 12491 | |||
| 12492 |
3/4✓ Branch 0 taken 1712989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1712988 times.
|
1712989 | DBUG_EXECUTE_IF("simulate_max_char_col", |
| 12493 | charset_no = MAX_CHAR_COLL_NUM + 1;); | ||
| 12494 | |||
| 12495 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1712988 times.
|
1712989 | if (charset_no > MAX_CHAR_COLL_NUM) { |
| 12496 | /* in data0type.h we assume that the | ||
| 12497 | number fits in one byte in prtype */ | ||
| 12498 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 12499 | ER_CANT_CREATE_TABLE, | ||
| 12500 | "In InnoDB, charset-collation codes" | ||
| 12501 | " must be below 256." | ||
| 12502 | " Unsupported code %lu.", | ||
| 12503 | (ulong)charset_no); | ||
| 12504 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | mem_heap_free(heap); |
| 12505 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dict_mem_table_free(table); |
| 12506 | |||
| 12507 | 1 | return ER_CANT_CREATE_TABLE; | |
| 12508 | } | ||
| 12509 | } | ||
| 12510 | |||
| 12511 |
1/2✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
|
3352330 | col_len = field->pack_length(); |
| 12512 | |||
| 12513 | /* The MySQL pack length contains 1 or 2 bytes length field | ||
| 12514 | for a true VARCHAR. Let us subtract that, so that the InnoDB | ||
| 12515 | column length in the InnoDB data dictionary is the real | ||
| 12516 | maximum byte length of the actual data. */ | ||
| 12517 | |||
| 12518 | 3352330 | long_true_varchar = 0; | |
| 12519 | |||
| 12520 |
3/4✓ Branch 0 taken 3352329 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1351959 times.
✓ Branch 3 taken 2000370 times.
|
3352330 | if (field->type() == MYSQL_TYPE_VARCHAR) { |
| 12521 |
1/2✓ Branch 0 taken 1351959 times.
✗ Branch 1 not taken.
|
1351959 | col_len -= field->get_length_bytes(); |
| 12522 | |||
| 12523 |
3/4✓ Branch 0 taken 1351959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 357452 times.
✓ Branch 3 taken 994507 times.
|
1351959 | if (field->get_length_bytes() == 2) { |
| 12524 | 357452 | long_true_varchar = DATA_LONG_TRUE_VARCHAR; | |
| 12525 | } | ||
| 12526 | } | ||
| 12527 | |||
| 12528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3352329 times.
|
3352329 | if (col_type == DATA_POINT) { |
| 12529 | ✗ | col_len = DATA_POINT_LEN; | |
| 12530 | } | ||
| 12531 | |||
| 12532 |
4/4✓ Branch 0 taken 9273 times.
✓ Branch 1 taken 3343056 times.
✓ Branch 2 taken 7046 times.
✓ Branch 3 taken 2227 times.
|
3352329 | is_virtual = (innobase_is_v_fld(field)) ? DATA_VIRTUAL : 0; |
| 12533 | 3352329 | is_stored = innobase_is_s_fld(field); | |
| 12534 | /* Check if the the field has COMPRESSED attribute */ | ||
| 12535 | 3352329 | compressed = (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) | |
| 12536 |
2/2✓ Branch 0 taken 411 times.
✓ Branch 1 taken 3351919 times.
|
3352330 | ? DATA_COMPRESSED |
| 12537 | : 0; | ||
| 12538 | |||
| 12539 |
3/4✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 3352092 times.
|
3352330 | is_multi_val = innobase_is_multi_value_fld(field) ? DATA_MULTI_VALUE : 0; |
| 12540 | |||
| 12541 | /* First check whether the column to be added has a | ||
| 12542 | system reserved name. */ | ||
| 12543 |
3/4✓ Branch 0 taken 3352330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3352328 times.
|
3352330 | if (dict_col_name_is_reserved(field_name)) { |
| 12544 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_WRONG_COLUMN_NAME, MYF(0), field_name); |
| 12545 | 2 | err_col: | |
| 12546 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_mem_table_free(table); |
| 12547 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | mem_heap_free(heap); |
| 12548 | |||
| 12549 | 2 | err = DB_ERROR; | |
| 12550 | 2 | goto error_ret; | |
| 12551 | } | ||
| 12552 | |||
| 12553 |
2/2✓ Branch 0 taken 3345282 times.
✓ Branch 1 taken 7046 times.
|
3352328 | if (!is_virtual) { |
| 12554 | 3345282 | uint32_t v_added = UINT32_UNDEFINED; | |
| 12555 | 3345282 | uint32_t v_dropped = UINT32_UNDEFINED; | |
| 12556 | 3345282 | uint32_t phy_pos = UINT32_UNDEFINED; | |
| 12557 | |||
| 12558 |
2/2✓ Branch 0 taken 288 times.
✓ Branch 1 taken 3344994 times.
|
3345282 | if (part_table_with_instant_cols) { |
| 12559 | const dd::Column *old_part_col = | ||
| 12560 |
1/2✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
|
288 | dd_find_column(old_part_table, field_name); |
| 12561 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
|
288 | ut_ad(old_part_col != nullptr); |
| 12562 | |||
| 12563 | /* Get version added */ | ||
| 12564 |
1/2✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
|
288 | v_added = dd_column_get_version_added(old_part_col); |
| 12565 | |||
| 12566 | /* This columns must be present */ | ||
| 12567 |
2/4✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 288 times.
|
288 | ut_ad(!dd_column_is_dropped(old_part_col)); |
| 12568 | |||
| 12569 | /* Get physical pos */ | ||
| 12570 | 288 | const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS]; | |
| 12571 |
4/8✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 288 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 288 times.
|
288 | ut_ad(old_part_col->se_private_data().exists(s)); |
| 12572 |
3/6✓ Branch 0 taken 288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 288 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 288 times.
✗ Branch 5 not taken.
|
288 | old_part_col->se_private_data().get(s, &phy_pos); |
| 12573 | } | ||
| 12574 | |||
| 12575 |
1/2✓ Branch 0 taken 3345282 times.
✗ Branch 1 not taken.
|
3345282 | dict_mem_table_add_col( |
| 12576 | table, heap, field_name, col_type, | ||
| 12577 | 6690562 | dtype_form_prtype((ulint)field->type() | nulls_allowed | | |
| 12578 |
1/2✓ Branch 0 taken 3345282 times.
✗ Branch 1 not taken.
|
3345281 | unsigned_type | binary_type | |
| 12579 | long_true_varchar | compressed, | ||
| 12580 | charset_no), | ||
| 12581 |
2/4✓ Branch 0 taken 3345281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3345281 times.
✗ Branch 3 not taken.
|
3345282 | col_len, !field->is_hidden_by_system(), phy_pos, v_added, v_dropped); |
| 12582 | |||
| 12583 |
3/4✓ Branch 0 taken 3345281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 3345169 times.
|
3345282 | if (dd_is_valid_row_version(v_added)) { |
| 12584 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | mem_heap_t *instant_heap = mem_heap_create(1000, UT_LOCATION_HERE); |
| 12585 | const dd::Column *old_part_col = | ||
| 12586 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | dd_find_column(old_part_table, field_name); |
| 12587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | ut_ad(old_part_col != nullptr); |
| 12588 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | dict_col_t *col = table->get_col(table->n_def - 1); |
| 12589 |
2/4✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
|
112 | dd_parse_default_value(old_part_col->se_private_data(), col, heap); |
| 12590 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | mem_heap_free(instant_heap); |
| 12591 | } | ||
| 12592 | } else { | ||
| 12593 |
2/2✓ Branch 0 taken 238 times.
✓ Branch 1 taken 6808 times.
|
7046 | if (is_multi_val) { |
| 12594 |
1/2✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
|
238 | col_len = field->key_length(); |
| 12595 | } | ||
| 12596 |
1/2✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
|
7046 | dict_mem_table_add_v_col( |
| 12597 | table, heap, field_name, col_type, | ||
| 12598 |
1/2✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
|
7046 | dtype_form_prtype((ulint)field->type() | nulls_allowed | |
| 12599 | 7046 | unsigned_type | binary_type | | |
| 12600 |
1/2✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
|
7046 | long_true_varchar | is_virtual | is_multi_val | |
| 12601 | compressed, | ||
| 12602 | charset_no), | ||
| 12603 | 7046 | col_len, i, field->gcol_info->non_virtual_base_columns(), | |
| 12604 |
1/2✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
|
7046 | !field->is_hidden_by_system()); |
| 12605 | } | ||
| 12606 | |||
| 12607 |
2/2✓ Branch 0 taken 2227 times.
✓ Branch 1 taken 3350100 times.
|
3352327 | if (is_stored) { |
| 12608 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2227 times.
|
2227 | ut_ad(!is_virtual); |
| 12609 | /* Added stored column in m_s_cols list. */ | ||
| 12610 |
1/2✓ Branch 0 taken 2227 times.
✗ Branch 1 not taken.
|
2227 | dict_mem_table_add_s_col(table, |
| 12611 | 2227 | field->gcol_info->non_virtual_base_columns()); | |
| 12612 | } | ||
| 12613 | } | ||
| 12614 | |||
| 12615 |
2/2✓ Branch 0 taken 3513 times.
✓ Branch 1 taken 425931 times.
|
429444 | if (num_v) { |
| 12616 |
2/2✓ Branch 0 taken 18958 times.
✓ Branch 1 taken 3513 times.
|
22471 | for (i = 0; i < n_cols; i++) { |
| 12617 | dict_v_col_t *v_col; | ||
| 12618 | |||
| 12619 | 18958 | Field *field = m_form->field[i]; | |
| 12620 | |||
| 12621 |
4/4✓ Branch 0 taken 9006 times.
✓ Branch 1 taken 9952 times.
✓ Branch 2 taken 1960 times.
✓ Branch 3 taken 7046 times.
|
18958 | if (!innobase_is_v_fld(field)) { |
| 12622 | 11912 | continue; | |
| 12623 | } | ||
| 12624 | |||
| 12625 |
1/2✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
|
7046 | v_col = dict_table_get_nth_v_col(table, j); |
| 12626 | |||
| 12627 | 7046 | j++; | |
| 12628 | |||
| 12629 |
1/2✓ Branch 0 taken 7046 times.
✗ Branch 1 not taken.
|
7046 | innodb_base_col_setup(table, field, v_col); |
| 12630 | } | ||
| 12631 | } | ||
| 12632 | |||
| 12633 | /** Fill base columns for the stored column present in the list. */ | ||
| 12634 |
5/6✓ Branch 0 taken 2131 times.
✓ Branch 1 taken 427313 times.
✓ Branch 2 taken 2131 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2131 times.
✓ Branch 5 taken 427313 times.
|
429444 | if (table->s_cols && table->s_cols->size()) { |
| 12635 |
2/2✓ Branch 0 taken 12449 times.
✓ Branch 1 taken 2131 times.
|
14580 | for (i = 0; i < n_cols; i++) { |
| 12636 | 12449 | Field *field = m_form->field[i]; | |
| 12637 | |||
| 12638 |
2/2✓ Branch 0 taken 10222 times.
✓ Branch 1 taken 2227 times.
|
12449 | if (!innobase_is_s_fld(field)) { |
| 12639 | 10222 | continue; | |
| 12640 | } | ||
| 12641 | |||
| 12642 | 2227 | dict_s_col_list::iterator it; | |
| 12643 |
1/2✓ Branch 0 taken 2390 times.
✗ Branch 1 not taken.
|
2390 | for (it = table->s_cols->begin(); it != table->s_cols->end(); ++it) { |
| 12644 | 2390 | dict_s_col_t s_col = *it; | |
| 12645 | |||
| 12646 |
2/2✓ Branch 0 taken 2227 times.
✓ Branch 1 taken 163 times.
|
2390 | if (s_col.s_pos == i) { |
| 12647 |
1/2✓ Branch 0 taken 2227 times.
✗ Branch 1 not taken.
|
2227 | innodb_base_col_setup_for_stored(table, field, &s_col); |
| 12648 | 2227 | break; | |
| 12649 | } | ||
| 12650 | } | ||
| 12651 | } | ||
| 12652 | } | ||
| 12653 | |||
| 12654 | /* Add the FTS doc_id hidden column. */ | ||
| 12655 |
4/4✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428851 times.
✓ Branch 2 taken 573 times.
✓ Branch 3 taken 20 times.
|
429444 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID) && !has_doc_id_col) { |
| 12656 |
1/2✓ Branch 0 taken 573 times.
✗ Branch 1 not taken.
|
573 | fts_add_doc_id_column(table, heap); |
| 12657 | } | ||
| 12658 | |||
| 12659 |
2/2✓ Branch 0 taken 413815 times.
✓ Branch 1 taken 15629 times.
|
429444 | if (keyring_encryption_option != FIL_ENCRYPTION_OFF) { |
| 12660 | 413815 | err = | |
| 12661 | 413815 | (Encryption::is_master_key_encryption(m_create_info->encrypt_type.str)) | |
| 12662 |
3/4✓ Branch 0 taken 4278 times.
✓ Branch 1 taken 409537 times.
✓ Branch 2 taken 4278 times.
✗ Branch 3 not taken.
|
413815 | ? enable_master_key_encryption(table) |
| 12663 |
1/2✓ Branch 0 taken 409537 times.
✗ Branch 1 not taken.
|
409537 | : enable_keyring_encryption(table, keyring_encryption_option); |
| 12664 | } | ||
| 12665 | |||
| 12666 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 429259 times.
|
429444 | if (err != DB_SUCCESS) { |
| 12667 |
1/2✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
|
185 | dict_mem_table_free(table); |
| 12668 |
1/2✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
|
185 | mem_heap_free(heap); |
| 12669 | 185 | goto error_ret; | |
| 12670 | } | ||
| 12671 | |||
| 12672 |
3/4✓ Branch 0 taken 429259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 228814 times.
✓ Branch 3 taken 200445 times.
|
429259 | if (table->is_temporary()) { |
| 12673 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 228813 times.
|
228814 | if (m_create_info->compress.length > 0) { |
| 12674 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 12675 | "InnoDB: Compression not supported for " | ||
| 12676 | "temporary tables"); | ||
| 12677 | |||
| 12678 | 1 | err = DB_UNSUPPORTED; | |
| 12679 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dict_mem_table_free(table); |
| 12680 | } else { | ||
| 12681 | /* Get a new table ID */ | ||
| 12682 |
1/2✓ Branch 0 taken 228813 times.
✗ Branch 1 not taken.
|
228813 | dict_table_assign_new_id(table); |
| 12683 | |||
| 12684 | /* Create temp tablespace if configured. */ | ||
| 12685 | 228813 | KeyringEncryptionKeyIdInfo keyring_encryption_key_id; | |
| 12686 | 228813 | keyring_encryption_key_id.was_encryption_key_id_set = false; | |
| 12687 |
1/2✓ Branch 0 taken 228812 times.
✗ Branch 1 not taken.
|
228813 | err = dict_build_tablespace_for_table(table, m_create_info, m_trx, |
| 12688 | FIL_ENCRYPTION_DEFAULT, | ||
| 12689 | keyring_encryption_key_id); | ||
| 12690 | |||
| 12691 |
2/2✓ Branch 0 taken 228809 times.
✓ Branch 1 taken 3 times.
|
228812 | if (err == DB_SUCCESS) { |
| 12692 | /* Temp-table are maintained in memory and so | ||
| 12693 | can_be_evicted is false. */ | ||
| 12694 | mem_heap_t *temp_table_heap; | ||
| 12695 | |||
| 12696 |
1/2✓ Branch 0 taken 228809 times.
✗ Branch 1 not taken.
|
228809 | temp_table_heap = mem_heap_create(256, UT_LOCATION_HERE); |
| 12697 | |||
| 12698 | /* For intrinsic table (given that they are | ||
| 12699 | not shared beyond session scope), add | ||
| 12700 | it to session specific THD structure | ||
| 12701 | instead of adding it to dictionary cache. */ | ||
| 12702 |
3/4✓ Branch 0 taken 228809 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182644 times.
✓ Branch 3 taken 46165 times.
|
228809 | if (table->is_intrinsic()) { |
| 12703 |
1/2✓ Branch 0 taken 182644 times.
✗ Branch 1 not taken.
|
182644 | add_table_to_thread_cache(table, temp_table_heap, m_thd); |
| 12704 | |||
| 12705 | } else { | ||
| 12706 |
1/2✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
|
46165 | dict_table_add_system_columns(table, temp_table_heap); |
| 12707 | |||
| 12708 |
1/2✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
|
46165 | dict_sys_mutex_enter(); |
| 12709 |
1/2✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
|
46165 | dict_table_add_to_cache(table, false); |
| 12710 |
1/2✓ Branch 0 taken 46165 times.
✗ Branch 1 not taken.
|
46165 | dict_sys_mutex_exit(); |
| 12711 | } | ||
| 12712 | |||
| 12713 |
4/6✓ Branch 0 taken 228809 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 228808 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
228809 | DBUG_EXECUTE_IF("ib_ddl_crash_during_create2", DBUG_SUICIDE();); |
| 12714 | |||
| 12715 |
1/2✓ Branch 0 taken 228808 times.
✗ Branch 1 not taken.
|
228808 | mem_heap_free(temp_table_heap); |
| 12716 | } else { | ||
| 12717 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | dict_mem_table_free(table); |
| 12718 | } | ||
| 12719 | } | ||
| 12720 | |||
| 12721 | } else { | ||
| 12722 | 200445 | const char *algorithm = m_create_info->compress.str; | |
| 12723 | |||
| 12724 | 200445 | err = DB_SUCCESS; | |
| 12725 | |||
| 12726 | 435895 | if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE) && | |
| 12727 |
6/6✓ Branch 0 taken 35005 times.
✓ Branch 1 taken 165440 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 35003 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 200443 times.
|
200447 | m_create_info->compress.length > 0 && |
| 12728 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | !Compression::is_none(algorithm)) { |
| 12729 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 12730 | "InnoDB: Compression not supported for " | ||
| 12731 | "shared tablespaces"); | ||
| 12732 | |||
| 12733 | 2 | algorithm = nullptr; | |
| 12734 | |||
| 12735 | 2 | err = DB_UNSUPPORTED; | |
| 12736 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | dict_mem_table_free(table); |
| 12737 | |||
| 12738 |
1/2✓ Branch 0 taken 200443 times.
✗ Branch 1 not taken.
|
200443 | } else if (Compression::validate(algorithm) != DB_SUCCESS || |
| 12739 |
6/6✓ Branch 0 taken 200442 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 200055 times.
✓ Branch 3 taken 387 times.
✓ Branch 4 taken 493 times.
✓ Branch 5 taken 199950 times.
|
400498 | m_form->s->row_type == ROW_TYPE_COMPRESSED || |
| 12740 |
2/2✓ Branch 0 taken 105 times.
✓ Branch 1 taken 199950 times.
|
200055 | m_create_info->key_block_size > 0) { |
| 12741 | 493 | algorithm = nullptr; | |
| 12742 | } | ||
| 12743 | |||
| 12744 | KeyringEncryptionKeyIdInfo keyring_encryption_key_id( | ||
| 12745 | 200445 | m_create_info->was_encryption_key_id_set, | |
| 12746 | 200445 | m_create_info->encryption_key_id); | |
| 12747 | |||
| 12748 |
2/2✓ Branch 0 taken 200443 times.
✓ Branch 1 taken 2 times.
|
200445 | if (err == DB_SUCCESS) { |
| 12749 |
1/2✓ Branch 0 taken 200397 times.
✗ Branch 1 not taken.
|
200443 | err = row_create_table_for_mysql(table, algorithm, m_create_info, m_trx, |
| 12750 | heap, | ||
| 12751 | keyring_encryption_option, | ||
| 12752 | keyring_encryption_key_id); | ||
| 12753 | |||
| 12754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 200397 times.
|
200397 | if (err == DB_IO_NO_PUNCH_HOLE_FS) { |
| 12755 | ✗ | ut_ad(!dict_table_in_shared_tablespace(table)); | |
| 12756 | ✗ | my_error(ER_INNODB_COMPRESSION_FAILURE, MYF(0), | |
| 12757 | "Punch hole not supported by the filesystem or the tablespace " | ||
| 12758 | "page size is not large enough."); | ||
| 12759 | } | ||
| 12760 | |||
| 12761 |
4/4✓ Branch 0 taken 200383 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 200310 times.
|
200397 | if (err == DB_SUCCESS && part_table_with_instant_cols) { |
| 12762 | /* Set phy_pos for system cols */ | ||
| 12763 | |||
| 12764 | 219 | auto fn = [&](uint32_t sys_col, const char *name) { | |
| 12765 | 219 | uint32_t phy_pos = UINT32_UNDEFINED; | |
| 12766 |
1/2✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
|
219 | dict_col_t *col = table->get_sys_col(sys_col); |
| 12767 |
1/2✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
|
219 | const dd::Column *old_part_col = dd_find_column(old_part_table, name); |
| 12768 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 157 times.
|
219 | if (old_part_col == nullptr) { |
| 12769 | /* If PK exists, DB_ROW_ID won't be part of table definition. */ | ||
| 12770 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | ut_ad(strcmp(name, "DB_ROW_ID") == 0); |
| 12771 | 62 | return; | |
| 12772 | } | ||
| 12773 | |||
| 12774 | 157 | const char *s = dd_column_key_strings[DD_INSTANT_PHYSICAL_POS]; | |
| 12775 |
4/8✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 157 times.
|
157 | ut_ad(old_part_col->se_private_data().exists(s)); |
| 12776 |
3/6✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
|
157 | old_part_col->se_private_data().get(s, &phy_pos); |
| 12777 | 157 | col->set_phy_pos(phy_pos); | |
| 12778 | 73 | }; | |
| 12779 | |||
| 12780 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | fn(DATA_ROW_ID, "DB_ROW_ID"); |
| 12781 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | fn(DATA_TRX_ID, "DB_TRX_ID"); |
| 12782 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | fn(DATA_ROLL_PTR, "DB_ROLL_PTR"); |
| 12783 | |||
| 12784 | /* Add INSTANT DROP columns metadata */ | ||
| 12785 | 73 | IF_DEBUG(uint32_t row_version = 0;) | |
| 12786 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | fill_dict_dropped_columns(old_part_table, table, |
| 12787 | IF_DEBUG(row_version, ) heap); | ||
| 12788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | ut_ad(row_version <= table->current_row_version); |
| 12789 | } | ||
| 12790 | } | ||
| 12791 | |||
| 12792 |
4/6✓ Branch 0 taken 200399 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 200379 times.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
200399 | DBUG_EXECUTE_IF("ib_crash_during_create_for_encryption", DBUG_SUICIDE();); |
| 12793 | } | ||
| 12794 | |||
| 12795 |
1/2✓ Branch 0 taken 429191 times.
✗ Branch 1 not taken.
|
429191 | mem_heap_free(heap); |
| 12796 | |||
| 12797 |
2/4✓ Branch 0 taken 429191 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 429191 times.
|
429191 | DBUG_EXECUTE_IF("ib_create_err_tablespace_exist", |
| 12798 | err = DB_TABLESPACE_EXISTS;); | ||
| 12799 | |||
| 12800 |
2/4✓ Branch 0 taken 429191 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 429191 times.
|
429191 | if (err == DB_DUPLICATE_KEY || err == DB_TABLESPACE_EXISTS) { |
| 12801 | char display_name[FN_REFLEN]; | ||
| 12802 | char *buf_end = | ||
| 12803 | ✗ | innobase_convert_identifier(display_name, sizeof(display_name) - 1, | |
| 12804 | ✗ | m_table_name, strlen(m_table_name), m_thd); | |
| 12805 | |||
| 12806 | ✗ | *buf_end = '\0'; | |
| 12807 | |||
| 12808 | ✗ | my_error( | |
| 12809 | err == DB_DUPLICATE_KEY ? ER_TABLE_EXISTS_ERROR : ER_TABLESPACE_EXISTS, | ||
| 12810 | MYF(0), display_name); | ||
| 12811 | |||
| 12812 | ✗ | if (err == DB_DUPLICATE_KEY) { | |
| 12813 | /* 'this' may not be ready for get_dup_key(), see same | ||
| 12814 | error tweaking in rename_table(). */ | ||
| 12815 | ✗ | err = DB_ERROR; | |
| 12816 | } | ||
| 12817 | } | ||
| 12818 | |||
| 12819 |
4/4✓ Branch 0 taken 429171 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 588 times.
✓ Branch 3 taken 428583 times.
|
429191 | if (err == DB_SUCCESS && (m_flags2 & DICT_TF2_FTS)) { |
| 12820 |
1/2✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
|
588 | dict_sys_mutex_enter(); |
| 12821 |
1/2✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
|
588 | fts_optimize_add_table(table); |
| 12822 |
1/2✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
|
588 | dict_sys_mutex_exit(); |
| 12823 | } | ||
| 12824 | |||
| 12825 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 429171 times.
|
429191 | if (err == DB_SUCCESS) { |
| 12826 | 429171 | m_table = table; | |
| 12827 | } | ||
| 12828 | |||
| 12829 | 20 | error_ret: | |
| 12830 |
1/2✓ Branch 0 taken 429379 times.
✗ Branch 1 not taken.
|
429379 | return convert_error_code_to_mysql(err, m_flags, m_thd); |
| 12831 | 429406 | } | |
| 12832 | |||
| 12833 | template <typename Index> | ||
| 12834 | const dd::Index *get_my_dd_index(const Index *index); | ||
| 12835 | |||
| 12836 | template <> | ||
| 12837 | 979 | const dd::Index *get_my_dd_index<dd::Index>(const dd::Index *dd_index) { | |
| 12838 | 979 | return dd_index; | |
| 12839 | } | ||
| 12840 | |||
| 12841 | template <> | ||
| 12842 | ✗ | const dd::Index *get_my_dd_index<dd::Partition_index>( | |
| 12843 | const dd::Partition_index *dd_index) { | ||
| 12844 | ✗ | return (dd_index != nullptr) ? &dd_index->index() : nullptr; | |
| 12845 | } | ||
| 12846 | |||
| 12847 | /** Creates an index in an InnoDB database. */ | ||
| 12848 | 191703 | inline int create_index( | |
| 12849 | trx_t *trx, /*!< in: InnoDB transaction handle */ | ||
| 12850 | const TABLE *form, /*!< in: information on table | ||
| 12851 | columns and indexes */ | ||
| 12852 | uint32_t flags, /*!< in: InnoDB table flags */ | ||
| 12853 | const char *table_name, /*!< in: table name */ | ||
| 12854 | uint key_num, /*!< in: index number */ | ||
| 12855 | const dd::Table *dd_table) /*!< in: dd::Table for the table*/ | ||
| 12856 | { | ||
| 12857 | dict_index_t *index; | ||
| 12858 | int error; | ||
| 12859 | const KEY *key; | ||
| 12860 | ulint ind_type; | ||
| 12861 | ulint *field_lengths; | ||
| 12862 | 191703 | uint32_t srid = 0; | |
| 12863 | 191703 | bool has_srid = false; | |
| 12864 | 191703 | bool multi_val_idx = false; | |
| 12865 | |||
| 12866 |
1/2✓ Branch 0 taken 191703 times.
✗ Branch 1 not taken.
|
191703 | DBUG_TRACE; |
| 12867 | |||
| 12868 | 191703 | key = form->key_info + key_num; | |
| 12869 | |||
| 12870 | /* Assert that "GEN_CLUST_INDEX" cannot be used as non-primary index */ | ||
| 12871 |
2/4✓ Branch 0 taken 191703 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 191703 times.
|
191703 | ut_a(innobase_strcasecmp(key->name, innobase_index_reserve_name) != 0); |
| 12872 | |||
| 12873 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 191702 times.
|
191703 | if (key->key_length == 0) { |
| 12874 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(ER_WRONG_KEY_COLUMN, MYF(0), key->key_part->field->field_name); |
| 12875 | 1 | return ER_WRONG_KEY_COLUMN; | |
| 12876 | } | ||
| 12877 | 191702 | ind_type = 0; | |
| 12878 |
2/2✓ Branch 0 taken 979 times.
✓ Branch 1 taken 190723 times.
|
191702 | if (key->flags & HA_SPATIAL) { |
| 12879 | 979 | ind_type = DICT_SPATIAL; | |
| 12880 |
2/2✓ Branch 0 taken 767 times.
✓ Branch 1 taken 189956 times.
|
190723 | } else if (key->flags & HA_FULLTEXT) { |
| 12881 | 767 | ind_type = DICT_FTS; | |
| 12882 | } | ||
| 12883 | |||
| 12884 |
2/2✓ Branch 0 taken 979 times.
✓ Branch 1 taken 190723 times.
|
191702 | if (ind_type == DICT_SPATIAL) { |
| 12885 |
2/2✓ Branch 0 taken 117 times.
✓ Branch 1 taken 862 times.
|
979 | ulint dd_index_num = key_num + ((form->s->primary_key == MAX_KEY) ? 1 : 0); |
| 12886 | |||
| 12887 |
2/4✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
|
979 | const auto *dd_index_auto = dd_table->indexes()[dd_index_num]; |
| 12888 | |||
| 12889 |
1/2✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
|
979 | const dd::Index *dd_index = get_my_dd_index(dd_index_auto); |
| 12890 |
2/4✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 979 times.
|
979 | ut_ad(dd_index->name() == key->name); |
| 12891 | |||
| 12892 | size_t geom_col_idx; | ||
| 12893 |
2/4✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
|
979 | for (geom_col_idx = 0; geom_col_idx < dd_index->elements().size(); |
| 12894 | ++geom_col_idx) { | ||
| 12895 |
5/10✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 979 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 979 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 979 times.
✗ Branch 9 not taken.
|
979 | if (!dd_index->elements()[geom_col_idx]->column().is_se_hidden()) break; |
| 12896 | } | ||
| 12897 |
3/6✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 979 times.
✗ Branch 5 not taken.
|
979 | const dd::Column &col = dd_index->elements()[geom_col_idx]->column(); |
| 12898 |
1/2✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
|
979 | has_srid = col.srs_id().has_value(); |
| 12899 |
4/6✓ Branch 0 taken 954 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 954 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 954 times.
✗ Branch 5 not taken.
|
979 | srid = has_srid ? col.srs_id().value() : 0; |
| 12900 | } | ||
| 12901 | |||
| 12902 |
2/2✓ Branch 0 taken 1746 times.
✓ Branch 1 taken 189956 times.
|
191702 | if (ind_type != 0) { |
| 12903 | 3492 | index = dict_mem_index_create(table_name, key->name, 0, ind_type, | |
| 12904 |
1/2✓ Branch 0 taken 1746 times.
✗ Branch 1 not taken.
|
1746 | key->user_defined_key_parts); |
| 12905 | |||
| 12906 |
2/2✓ Branch 0 taken 1879 times.
✓ Branch 1 taken 1746 times.
|
3625 | for (ulint i = 0; i < key->user_defined_key_parts; i++) { |
| 12907 | 1879 | KEY_PART_INFO *key_part = key->key_part + i; | |
| 12908 | |||
| 12909 | /* We do not support special (Fulltext or Spatial) | ||
| 12910 | index on virtual columns */ | ||
| 12911 |
3/4✓ Branch 0 taken 44 times.
✓ Branch 1 taken 1835 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
|
1879 | if (innobase_is_v_fld(key_part->field)) { |
| 12912 | ✗ | ut_d(ut_error); | |
| 12913 | ut_o(return HA_ERR_UNSUPPORTED); | ||
| 12914 | } | ||
| 12915 | |||
| 12916 | 1879 | index->add_field(key_part->field->field_name, 0, | |
| 12917 |
1/2✓ Branch 0 taken 1879 times.
✗ Branch 1 not taken.
|
1879 | !(key_part->key_part_flag & HA_REVERSE_SORT)); |
| 12918 | } | ||
| 12919 | |||
| 12920 |
2/2✓ Branch 0 taken 979 times.
✓ Branch 1 taken 767 times.
|
1746 | if (ind_type == DICT_SPATIAL) { |
| 12921 | 979 | index->srid_is_valid = has_srid; | |
| 12922 | 979 | index->srid = srid; | |
| 12923 |
1/2✓ Branch 0 taken 979 times.
✗ Branch 1 not taken.
|
979 | index->rtr_srs.reset(fetch_srs(index->srid)); |
| 12924 | } | ||
| 12925 | |||
| 12926 |
2/4✓ Branch 0 taken 1746 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1746 times.
✗ Branch 3 not taken.
|
1746 | return convert_error_code_to_mysql( |
| 12927 | row_create_index_for_mysql(index, trx, nullptr, nullptr), flags, | ||
| 12928 | 1746 | nullptr); | |
| 12929 | } | ||
| 12930 | |||
| 12931 | 189956 | ind_type = 0; | |
| 12932 | |||
| 12933 |
2/2✓ Branch 0 taken 118783 times.
✓ Branch 1 taken 71173 times.
|
189956 | if (key_num == form->s->primary_key) { |
| 12934 | 118783 | ind_type |= DICT_CLUSTERED; | |
| 12935 | } | ||
| 12936 | |||
| 12937 |
2/2✓ Branch 0 taken 152250 times.
✓ Branch 1 taken 37706 times.
|
189956 | if (key->flags & HA_NOSAME) { |
| 12938 | 152250 | ind_type |= DICT_UNIQUE; | |
| 12939 | } | ||
| 12940 | |||
| 12941 | 379912 | field_lengths = (ulint *)my_malloc( | |
| 12942 |
1/2✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
|
189956 | PSI_INSTRUMENT_ME, key->user_defined_key_parts * sizeof *field_lengths, |
| 12943 | MYF(MY_FAE)); | ||
| 12944 | |||
| 12945 | /* We pass 0 as the space id, and determine at a lower level the space | ||
| 12946 | id where to store the table */ | ||
| 12947 | |||
| 12948 | 379912 | index = dict_mem_index_create(table_name, key->name, 0, ind_type, | |
| 12949 |
1/2✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
|
189956 | key->user_defined_key_parts); |
| 12950 | |||
| 12951 |
1/2✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
|
189956 | innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd); |
| 12952 |
1/2✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
|
189956 | dict_table_t *handler = priv->lookup_table_handler(table_name); |
| 12953 | |||
| 12954 |
2/2✓ Branch 0 taken 3128 times.
✓ Branch 1 taken 186828 times.
|
189956 | if (handler != nullptr) { |
| 12955 | /* This setting will enforce SQL NULL == SQL NULL. | ||
| 12956 | For now this is turned-on for intrinsic tables | ||
| 12957 | only but can be turned on for other tables if needed arises. */ | ||
| 12958 | 3128 | index->nulls_equal = (key->flags & HA_NULL_ARE_EQUAL) ? true : false; | |
| 12959 | |||
| 12960 | /* Disable use of AHI for intrinsic table indexes as AHI | ||
| 12961 | validates the predicated entry using index-id which has to be | ||
| 12962 | system-wide unique that is not the case with indexes of | ||
| 12963 | intrinsic table for performance reason. | ||
| 12964 | Also given the lifetime of these tables and frequent delete | ||
| 12965 | and update AHI would not help on performance front as it does | ||
| 12966 | with normal tables. */ | ||
| 12967 | 3128 | index->disable_ahi = true; | |
| 12968 | } | ||
| 12969 | |||
| 12970 |
2/2✓ Branch 0 taken 253708 times.
✓ Branch 1 taken 189956 times.
|
443664 | for (ulint i = 0; i < key->user_defined_key_parts; i++) { |
| 12971 | 253708 | KEY_PART_INFO *key_part = key->key_part + i; | |
| 12972 | ulint prefix_len; | ||
| 12973 | ulint col_type; | ||
| 12974 | ulint is_unsigned; | ||
| 12975 | |||
| 12976 | /* (The flag HA_PART_KEY_SEG denotes in MySQL a | ||
| 12977 | column prefix field in an index: we only store a | ||
| 12978 | specified number of first bytes of the column to | ||
| 12979 | the index field.) The flag does not seem to be | ||
| 12980 | properly set by MySQL. Let us fall back on testing | ||
| 12981 | the length of the key part versus the column. | ||
| 12982 | We first reach to the table's column; if the index is on a | ||
| 12983 | prefix, key_part->field is not the table's column (it's a | ||
| 12984 | "fake" field forged in open_table_from_share() with length | ||
| 12985 | equal to the length of the prefix); so we have to go to | ||
| 12986 | form->fied. */ | ||
| 12987 | 253708 | Field *field = form->field[key_part->field->field_index()]; | |
| 12988 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 253708 times.
|
253708 | if (field == nullptr) ut_error; |
| 12989 | |||
| 12990 | 253708 | const char *field_name = key_part->field->field_name; | |
| 12991 |
6/8✓ Branch 0 taken 4034 times.
✓ Branch 1 taken 249674 times.
✓ Branch 2 taken 4034 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4034 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4034 times.
✓ Branch 7 taken 249674 times.
|
253708 | if (handler != nullptr && handler->is_intrinsic()) { |
| 12992 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 4034 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4034 times.
|
4034 | ut_ad(!innobase_is_v_fld(key_part->field)); |
| 12993 | ulint col_no = | ||
| 12994 |
2/4✓ Branch 0 taken 4034 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4034 times.
✗ Branch 3 not taken.
|
4034 | dict_col_get_no(handler->get_col(key_part->field->field_index())); |
| 12995 |
1/2✓ Branch 0 taken 4034 times.
✗ Branch 1 not taken.
|
4034 | field_name = handler->get_col_name(col_no); |
| 12996 | } | ||
| 12997 | |||
| 12998 |
1/2✓ Branch 0 taken 253708 times.
✗ Branch 1 not taken.
|
253708 | col_type = get_innobase_type_from_mysql_type(&is_unsigned, key_part->field); |
| 12999 | |||
| 13000 | /* Multi-value prefix index is not supported. */ | ||
| 13001 |
7/8✓ Branch 0 taken 253708 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 253470 times.
✓ Branch 3 taken 238 times.
✓ Branch 4 taken 234377 times.
✓ Branch 5 taken 19093 times.
✓ Branch 6 taken 20040 times.
✓ Branch 7 taken 233668 times.
|
741555 | if (!innobase_is_multi_value_fld(key_part->field) && |
| 13002 | 253470 | (DATA_LARGE_MTYPE(col_type) || | |
| 13003 |
3/4✓ Branch 0 taken 234377 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55329 times.
✓ Branch 3 taken 179048 times.
|
234377 | (key_part->length < field->pack_length() && |
| 13004 |
3/4✓ Branch 0 taken 55329 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54830 times.
✓ Branch 3 taken 499 times.
|
55329 | field->type() != MYSQL_TYPE_VARCHAR) || |
| 13005 |
3/4✓ Branch 0 taken 233878 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54830 times.
✓ Branch 3 taken 179048 times.
|
233878 | (field->type() == MYSQL_TYPE_VARCHAR && |
| 13006 | 54830 | key_part->length < | |
| 13007 |
4/6✓ Branch 0 taken 54830 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54830 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 448 times.
✓ Branch 5 taken 54382 times.
|
54830 | field->pack_length() - field->get_length_bytes()))) { |
| 13008 |
1/2✓ Branch 0 taken 20040 times.
✗ Branch 1 not taken.
|
20040 | switch (col_type) { |
| 13009 | 20040 | default: | |
| 13010 | 20040 | prefix_len = key_part->length; | |
| 13011 | 20040 | break; | |
| 13012 | ✗ | case DATA_INT: | |
| 13013 | case DATA_FLOAT: | ||
| 13014 | case DATA_DOUBLE: | ||
| 13015 | case DATA_DECIMAL: | ||
| 13016 | ✗ | log_errlog(ERROR_LEVEL, ER_WRONG_TYPE_FOR_COLUMN_PREFIX_IDX_FLD, | |
| 13017 | table_name, key_part->field->field_name); | ||
| 13018 | |||
| 13019 | ✗ | prefix_len = 0; | |
| 13020 | } | ||
| 13021 | } else { | ||
| 13022 | 233668 | prefix_len = 0; | |
| 13023 | } | ||
| 13024 | |||
| 13025 | 253708 | field_lengths[i] = key_part->length; | |
| 13026 | |||
| 13027 |
7/10✓ Branch 0 taken 5094 times.
✓ Branch 1 taken 248614 times.
✓ Branch 2 taken 1016 times.
✓ Branch 3 taken 4078 times.
✓ Branch 4 taken 249630 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 249630 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 253708 times.
|
253708 | ut_ad(!(!innobase_is_v_fld(key_part->field) && |
| 13028 | innobase_is_multi_value_fld(key_part->field))); | ||
| 13029 | |||
| 13030 |
4/4✓ Branch 0 taken 5094 times.
✓ Branch 1 taken 248614 times.
✓ Branch 2 taken 4078 times.
✓ Branch 3 taken 1016 times.
|
253708 | if (innobase_is_v_fld(key_part->field)) { |
| 13031 | 4078 | index->type |= DICT_VIRTUAL; | |
| 13032 | |||
| 13033 |
3/4✓ Branch 0 taken 4078 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 3840 times.
|
4078 | if (innobase_is_multi_value_fld(key_part->field)) { |
| 13034 | 238 | index->type |= DICT_MULTI_VALUE; | |
| 13035 | } | ||
| 13036 | } | ||
| 13037 | |||
| 13038 | 253708 | index->add_field(field_name, prefix_len, | |
| 13039 |
1/2✓ Branch 0 taken 253708 times.
✗ Branch 1 not taken.
|
253708 | !(key_part->key_part_flag & HA_REVERSE_SORT)); |
| 13040 | } | ||
| 13041 | |||
| 13042 |
3/6✓ Branch 0 taken 189956 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 189956 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 189956 times.
|
189956 | ut_ad(key->flags & HA_FULLTEXT || !(index->type & DICT_FTS)); |
| 13043 | |||
| 13044 | 189956 | multi_val_idx = ((index->type & DICT_MULTI_VALUE) == DICT_MULTI_VALUE); | |
| 13045 | |||
| 13046 | /* Even though we've defined max_supported_key_part_length, we | ||
| 13047 | still do our own checking using field_lengths to be absolutely | ||
| 13048 | sure we don't create too long indexes. */ | ||
| 13049 | |||
| 13050 |
2/4✓ Branch 0 taken 189855 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 189855 times.
✗ Branch 3 not taken.
|
189956 | error = convert_error_code_to_mysql( |
| 13051 | row_create_index_for_mysql(index, trx, field_lengths, handler), flags, | ||
| 13052 | nullptr); | ||
| 13053 | |||
| 13054 | /* For multi-value virtual index, we need to adjust indexed col length */ | ||
| 13055 |
4/4✓ Branch 0 taken 189841 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 238 times.
✓ Branch 3 taken 189603 times.
|
189855 | if (error == 0 && multi_val_idx) { |
| 13056 |
1/2✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
|
238 | dict_table_t *new_table = dd_table_open_on_name_in_mem(table_name, false); |
| 13057 | |||
| 13058 | 238 | dict_index_t *last_index = UT_LIST_GET_LAST(new_table->indexes); | |
| 13059 |
2/2✓ Branch 0 taken 513 times.
✓ Branch 1 taken 238 times.
|
751 | for (unsigned int i = 0; i < last_index->n_fields; i++) { |
| 13060 |
4/4✓ Branch 0 taken 238 times.
✓ Branch 1 taken 275 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 357 times.
|
751 | if (last_index->fields[i].col->is_multi_value() && |
| 13061 |
2/2✓ Branch 0 taken 156 times.
✓ Branch 1 taken 82 times.
|
238 | (last_index->fields[i].fixed_len != 0)) { |
| 13062 | 156 | last_index->fields[i].fixed_len = field_lengths[i]; | |
| 13063 | } | ||
| 13064 | } | ||
| 13065 | |||
| 13066 |
1/2✓ Branch 0 taken 238 times.
✗ Branch 1 not taken.
|
238 | dd_table_close(new_table, nullptr, nullptr, false); |
| 13067 | } | ||
| 13068 | |||
| 13069 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 189841 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
189855 | if (error && handler != nullptr) { |
| 13070 | ✗ | priv->unregister_table_handler(table_name); | |
| 13071 | } | ||
| 13072 | |||
| 13073 |
1/2✓ Branch 0 taken 189855 times.
✗ Branch 1 not taken.
|
189855 | my_free(field_lengths); |
| 13074 | |||
| 13075 | 189855 | return error; | |
| 13076 | 191602 | } | |
| 13077 | |||
| 13078 | /** Creates an index to an InnoDB table when the user has defined no | ||
| 13079 | primary index. */ | ||
| 13080 | 310387 | inline int create_clustered_index_when_no_primary( | |
| 13081 | trx_t *trx, /*!< in: InnoDB transaction handle */ | ||
| 13082 | uint32_t flags, /*!< in: InnoDB table flags */ | ||
| 13083 | const char *table_name) /*!< in: table name */ | ||
| 13084 | { | ||
| 13085 | dict_index_t *index; | ||
| 13086 | dberr_t error; | ||
| 13087 | |||
| 13088 | /* We pass 0 as the space id, and determine at a lower level the space | ||
| 13089 | id where to store the table */ | ||
| 13090 | 310387 | index = dict_mem_index_create(table_name, innobase_index_reserve_name, 0, | |
| 13091 | DICT_CLUSTERED, 0); | ||
| 13092 | |||
| 13093 | 310387 | innodb_session_t *&priv = thd_to_innodb_session(trx->mysql_thd); | |
| 13094 | |||
| 13095 | 310387 | dict_table_t *handler = priv->lookup_table_handler(table_name); | |
| 13096 | |||
| 13097 |
2/2✓ Branch 0 taken 181887 times.
✓ Branch 1 taken 128500 times.
|
310387 | if (handler != nullptr) { |
| 13098 | /* Disable use of AHI for intrinsic table indexes as AHI | ||
| 13099 | validates the predicated entry using index-id which has to be | ||
| 13100 | system-wide unique that is not the case with indexes of | ||
| 13101 | intrinsic table for performance reason. | ||
| 13102 | Also given the lifetime of these tables and frequent delete | ||
| 13103 | and update AHI would not help on performance front as it does | ||
| 13104 | with normal tables. */ | ||
| 13105 | 181887 | index->disable_ahi = true; | |
| 13106 | } | ||
| 13107 | |||
| 13108 | 310387 | error = row_create_index_for_mysql(index, trx, nullptr, handler); | |
| 13109 | |||
| 13110 |
3/4✓ Branch 0 taken 25 times.
✓ Branch 1 taken 310362 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
|
310387 | if (error != DB_SUCCESS && handler != nullptr) { |
| 13111 | ✗ | priv->unregister_table_handler(table_name); | |
| 13112 | } | ||
| 13113 | |||
| 13114 | 310387 | return (convert_error_code_to_mysql(error, flags, nullptr)); | |
| 13115 | } | ||
| 13116 | |||
| 13117 | 26 | void create_table_info_t::log_error_invalid_location(std::string &msg, | |
| 13118 | bool ignore) { | ||
| 13119 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 18 times.
|
26 | if (ignore) { |
| 13120 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | THD *thd = current_thd; |
| 13121 | |||
| 13122 | 8 | constexpr char ignored_msg[] = | |
| 13123 | " The DATA DIRECTORY location will be ignored and the" | ||
| 13124 | " file will be put into the default datadir location."; | ||
| 13125 | |||
| 13126 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | msg.append(ignored_msg); |
| 13127 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_FILE_NAME, |
| 13128 | "%s", msg.c_str()); | ||
| 13129 | |||
| 13130 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | ib::warn(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str()); |
| 13131 | } else { | ||
| 13132 | 18 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); | |
| 13133 | |||
| 13134 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLE, m_table_name, msg.c_str()); |
| 13135 | } | ||
| 13136 | 26 | } | |
| 13137 | |||
| 13138 | 892 | bool create_table_info_t::create_option_data_directory_is_valid(bool ignore) { | |
| 13139 | 892 | bool is_valid = true; | |
| 13140 | |||
| 13141 |
3/6✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 892 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 892 times.
|
892 | ut_ad(m_create_info->data_file_name != nullptr && |
| 13142 | *m_create_info->data_file_name != '\0'); | ||
| 13143 | |||
| 13144 | /* Use DATA DIRECTORY only with file-per-table. */ | ||
| 13145 |
3/4✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 884 times.
|
892 | if (!m_use_shared_space && !m_allow_file_per_table) { |
| 13146 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, |
| 13147 | "InnoDB: DATA DIRECTORY requires" | ||
| 13148 | " innodb_file_per_table."); | ||
| 13149 | 8 | is_valid = false; | |
| 13150 | } | ||
| 13151 | |||
| 13152 | /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */ | ||
| 13153 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 886 times.
|
892 | if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 13154 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, |
| 13155 | "InnoDB: DATA DIRECTORY cannot be used" | ||
| 13156 | " for TEMPORARY tables."); | ||
| 13157 | 6 | is_valid = false; | |
| 13158 | } | ||
| 13159 | |||
| 13160 | /* We checked previously for a conflicting DATA DIRECTORY mixed | ||
| 13161 | with TABLESPACE in create_option_tablespace_is_valid(). | ||
| 13162 | An ALTER TABLE statement might have both if it is being moved. | ||
| 13163 | So if m_tablespace is set, don't check the existing data_file_name. */ | ||
| 13164 |
2/2✓ Branch 0 taken 206 times.
✓ Branch 1 taken 686 times.
|
892 | if (m_create_info->tablespace != nullptr) { |
| 13165 | 206 | return (is_valid); | |
| 13166 | } | ||
| 13167 | |||
| 13168 | #ifndef UNIV_HOTBACKUP | ||
| 13169 | /* Validate the directory location. */ | ||
| 13170 | 686 | bool suffixed_table_name = !m_partition; | |
| 13171 |
3/6✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 686 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 686 times.
✗ Branch 5 not taken.
|
686 | char *filepath = Fil_path::make(m_create_info->data_file_name, m_table_name, |
| 13172 | IBD, suffixed_table_name); | ||
| 13173 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | size_t dirname_len = dirname_length(filepath); |
| 13174 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | Fil_path dirpath(filepath, dirname_len, true); |
| 13175 | |||
| 13176 | /* Do not allow the file to be created in a unique undo directory. */ | ||
| 13177 |
6/8✓ Branch 0 taken 43 times.
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 683 times.
|
729 | if (MySQL_undo_path_is_unique && (MySQL_undo_path.is_same_as(dirpath) || |
| 13178 |
3/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 40 times.
|
43 | MySQL_undo_path.is_ancestor(dirpath))) { |
| 13179 | std::string msg( | ||
| 13180 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | "The DATA DIRECTORY location cannot be the undo directory."); |
| 13181 | |||
| 13182 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | log_error_invalid_location(msg, ignore); |
| 13183 | |||
| 13184 | 3 | is_valid = false; | |
| 13185 | 3 | } | |
| 13186 | |||
| 13187 | /* Do not allow a file-per-table tablespace in the datadir. | ||
| 13188 | In order to be located in the datadir, one must use a schama name | ||
| 13189 | identical to the datadir directory and the datadir parent must be | ||
| 13190 | used as the DATA DIRECTORY.*/ | ||
| 13191 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | bool in_datadir = MySQL_datadir_path.is_same_as(dirpath); |
| 13192 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 684 times.
|
686 | if (in_datadir) { |
| 13193 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | std::string msg("The DATA DIRECTORY location cannot be the datadir."); |
| 13194 | |||
| 13195 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | log_error_invalid_location(msg, ignore); |
| 13196 | |||
| 13197 | 2 | is_valid = false; | |
| 13198 | 2 | } | |
| 13199 | |||
| 13200 | /* Do not allow a datafile outside the known directories. */ | ||
| 13201 |
1/2✓ Branch 0 taken 686 times.
✗ Branch 1 not taken.
|
686 | bool under_datadir = MySQL_datadir_path.is_ancestor(dirpath); |
| 13202 | bool in_known_location = | ||
| 13203 |
6/8✓ Branch 0 taken 684 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 684 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 684 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 663 times.
✓ Branch 7 taken 21 times.
|
686 | (in_datadir || under_datadir) ? true : fil_path_is_known(dirpath.path()); |
| 13204 | |||
| 13205 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 665 times.
|
686 | if (!in_known_location) { |
| 13206 | std::string msg( | ||
| 13207 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | "The DATA DIRECTORY location must be in a known directory."); |
| 13208 | |||
| 13209 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | log_error_invalid_location(msg, ignore); |
| 13210 | |||
| 13211 | 21 | is_valid = false; | |
| 13212 | 21 | } | |
| 13213 | |||
| 13214 | 686 | ut::free(filepath); | |
| 13215 | #endif /* UNIV_HOTBACKUP */ | ||
| 13216 | |||
| 13217 | 686 | return (is_valid); | |
| 13218 | 686 | } | |
| 13219 | |||
| 13220 | /** Validate the tablespace name provided for a tablespace DDL | ||
| 13221 | @param[in] ts_command tablespace command type | ||
| 13222 | @param[in] name A proposed tablespace name | ||
| 13223 | @return MySQL handler error code like HA_... */ | ||
| 13224 | 501694 | static int validate_tablespace_name(ts_command_type ts_command, | |
| 13225 | const char *name) { | ||
| 13226 | 501694 | int err = 0; | |
| 13227 | |||
| 13228 | /* This prefix is reserved by InnoDB for use in internal tablespace | ||
| 13229 | names. */ | ||
| 13230 | 501694 | const char reserved_space_name_prefix[] = "innodb_"; | |
| 13231 | |||
| 13232 | /* Validation at the SQL layer should already be completed at this | ||
| 13233 | stage. Re-assert that the length is valid. */ | ||
| 13234 |
2/4✓ Branch 0 taken 501694 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 501694 times.
|
501694 | if (validate_tablespace_name_length(name)) { |
| 13235 | ✗ | my_printf_error(ER_WRONG_TABLESPACE_NAME, | |
| 13236 | "InnoDB: Tablespace name `%s` is too long.", MYF(0), name); | ||
| 13237 | ✗ | return (HA_WRONG_CREATE_OPTION); | |
| 13238 | } | ||
| 13239 | |||
| 13240 | /* The tablespace name cannot start with `innodb_`. */ | ||
| 13241 |
2/2✓ Branch 0 taken 22006 times.
✓ Branch 1 taken 479688 times.
|
501694 | if (strlen(name) >= sizeof(reserved_space_name_prefix) - 1 && |
| 13242 |
2/2✓ Branch 0 taken 2058 times.
✓ Branch 1 taken 19948 times.
|
22006 | 0 == memcmp(name, reserved_space_name_prefix, |
| 13243 | sizeof(reserved_space_name_prefix) - 1)) { | ||
| 13244 | /* Use a different message for reserved names */ | ||
| 13245 |
2/2✓ Branch 0 taken 1070 times.
✓ Branch 1 taken 988 times.
|
2058 | if (0 == strcmp(name, dict_sys_t::s_file_per_table_name) || |
| 13246 |
2/2✓ Branch 0 taken 308 times.
✓ Branch 1 taken 762 times.
|
1070 | 0 == strcmp(name, dict_sys_t::s_sys_space_name) || |
| 13247 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 271 times.
|
308 | 0 == strcmp(name, dict_sys_t::s_temp_space_name)) { |
| 13248 | /* Allow these names if the caller is putting a | ||
| 13249 | table into one of these by CREATE/ALTER TABLE */ | ||
| 13250 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1770 times.
|
1787 | if (ts_command != TS_CMD_NOT_DEFINED) { |
| 13251 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 13252 | "InnoDB: `%s` is a reserved" | ||
| 13253 | " tablespace name.", | ||
| 13254 | MYF(0), name); | ||
| 13255 | 17 | err = HA_WRONG_CREATE_OPTION; | |
| 13256 | } | ||
| 13257 | } else { | ||
| 13258 | /* Allow any undo tablespace to be set active or inactive. | ||
| 13259 | And any undo tablespace can be dropped except the default two | ||
| 13260 | implicit spaces. All other DDL should not work on tablespaces | ||
| 13261 | that start with "innodb_". */ | ||
| 13262 | 271 | bool allow = | |
| 13263 |
4/4✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 20 times.
|
278 | (ts_command == ALTER_UNDO_TABLESPACE || |
| 13264 | 7 | (ts_command == DROP_UNDO_TABLESPACE && | |
| 13265 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_1) && |
| 13266 | ✗ | 0 != strcmp(name, dict_sys_t::s_default_undo_space_name_2))); | |
| 13267 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 244 times.
|
271 | if (!allow) { |
| 13268 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 13269 | "InnoDB: Tablespace names starting" | ||
| 13270 | " with `%s` are reserved.", | ||
| 13271 | MYF(0), reserved_space_name_prefix); | ||
| 13272 | 27 | err = HA_WRONG_CREATE_OPTION; | |
| 13273 | } | ||
| 13274 | } | ||
| 13275 |
2/2✓ Branch 0 taken 473445 times.
✓ Branch 1 taken 26191 times.
|
501694 | } else if (0 == strcmp(name, dict_sys_t::s_dd_space_name)) { |
| 13276 | /* mysql tablespace can't be created or dropped */ | ||
| 13277 |
4/4✓ Branch 0 taken 473441 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 473434 times.
|
473445 | if (ts_command == CREATE_TABLESPACE || ts_command == DROP_TABLESPACE) { |
| 13278 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 13279 | "InnoDB: `mysql` is a reserved" | ||
| 13280 | " tablespace name.", | ||
| 13281 | MYF(0)); | ||
| 13282 | 11 | err = HA_WRONG_CREATE_OPTION; | |
| 13283 | } | ||
| 13284 | } | ||
| 13285 | |||
| 13286 | /* The tablespace name cannot contain a '/'. */ | ||
| 13287 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 501687 times.
|
501694 | if (memchr(name, '/', strlen(name)) != nullptr) { |
| 13288 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 13289 | "InnoDB: A general tablespace name cannot" | ||
| 13290 | " contain '/'.", | ||
| 13291 | MYF(0)); | ||
| 13292 | 7 | err = HA_WRONG_CREATE_OPTION; | |
| 13293 | } | ||
| 13294 | |||
| 13295 | 501694 | return (err); | |
| 13296 | } | ||
| 13297 | |||
| 13298 | 441225 | bool innobase_is_valid_tablespace_name(ts_command_type ts_cmd, | |
| 13299 | const char *name) { | ||
| 13300 | 441225 | return (0 == validate_tablespace_name(ts_cmd, name)); | |
| 13301 | } | ||
| 13302 | |||
| 13303 | /** Validate TABLESPACE option. | ||
| 13304 | @return true if valid, false if not. */ | ||
| 13305 | 458916 | bool create_table_info_t::create_option_tablespace_is_valid() { | |
| 13306 | 458916 | bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 13307 | 458916 | bool is_file_per_table = tablespace_is_file_per_table(m_create_info); | |
| 13308 | 458916 | bool is_general_space = tablespace_is_general_space(m_create_info); | |
| 13309 | 458916 | bool is_temp_space = | |
| 13310 |
2/2✓ Branch 0 taken 68805 times.
✓ Branch 1 taken 390111 times.
|
527721 | (m_create_info->tablespace && |
| 13311 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 68788 times.
|
68805 | strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0); |
| 13312 | |||
| 13313 | /* Do not allow creation of a temp table | ||
| 13314 | with innodb_file_per_table or innodb_temporary option. */ | ||
| 13315 |
6/6✓ Branch 0 taken 228908 times.
✓ Branch 1 taken 230008 times.
✓ Branch 2 taken 228906 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 228893 times.
|
458916 | if (is_temp && (is_file_per_table || is_temp_space)) { |
| 13316 |
7/8✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 14 times.
|
15 | if (THDVAR(m_thd, strict_mode) && is_file_per_table) { |
| 13317 | 1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13318 | "InnoDB: TABLESPACE=%s option" | ||
| 13319 | " is disallowed for temporary tables" | ||
| 13320 | " with INNODB_STRICT_MODE=ON. This option is" | ||
| 13321 | " deprecated and will be removed in a future release", | ||
| 13322 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | MYF(0), m_create_info->tablespace); |
| 13323 | 1 | return false; | |
| 13324 | } | ||
| 13325 | |||
| 13326 | /* STRICT mode turned off. Proceed with the execution with | ||
| 13327 | a deprecation warning */ | ||
| 13328 | 14 | push_warning_printf( | |
| 13329 | m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13330 | "InnoDB: TABLESPACE=%s option is ignored. All temporary tables" | ||
| 13331 | " are created in a session temporary tablespace. This option" | ||
| 13332 | " is deprecated and will be removed in a future release.", | ||
| 13333 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | m_create_info->tablespace); |
| 13334 | } | ||
| 13335 | |||
| 13336 | /* Check the encryption option validity. */ | ||
| 13337 |
6/6✓ Branch 0 taken 105443 times.
✓ Branch 1 taken 353472 times.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 105397 times.
✓ Branch 4 taken 46 times.
✓ Branch 5 taken 458869 times.
|
564358 | if (m_create_info->encrypt_type.str != nullptr && |
| 13338 | 105443 | Encryption::validate(m_create_info->encrypt_type.str) == DB_UNSUPPORTED) { | |
| 13339 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); |
| 13340 | 46 | return false; | |
| 13341 | } | ||
| 13342 | |||
| 13343 |
2/2✓ Branch 0 taken 412851 times.
✓ Branch 1 taken 46018 times.
|
458869 | if (!m_use_shared_space) { |
| 13344 |
2/2✓ Branch 0 taken 233418 times.
✓ Branch 1 taken 179433 times.
|
412851 | if (!m_use_file_per_table) { |
| 13345 |
2/2✓ Branch 0 taken 1157 times.
✓ Branch 1 taken 232261 times.
|
233418 | if (m_create_info->encrypt_type.str != nullptr && |
| 13346 |
4/4✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1101 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 11 times.
|
1157 | m_create_info->explicit_encryption && is_temp) { |
| 13347 | /* Temporary tablespace is being used for table */ | ||
| 13348 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 13349 | "InnoDB: ENCRYPTION is not accepted" | ||
| 13350 | " for temporary tablespace. For temporary tablespace" | ||
| 13351 | " encryption please use innodb_temp_tablespace_encrypt" | ||
| 13352 | " variable.", | ||
| 13353 | MYF(0)); | ||
| 13354 | 45 | return false; | |
| 13355 | } | ||
| 13356 | |||
| 13357 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 233372 times.
|
233373 | if (m_create_info->m_implicit_tablespace_autoextend_size > 0) { |
| 13358 | /* AUTOEXTEND_SIZE is not allowed for system tablespace. */ | ||
| 13359 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 13360 | "InnoDB : AUTOEXTEND_SIZE is not accepted" | ||
| 13361 | " for system tablespace.", | ||
| 13362 | MYF(0)); | ||
| 13363 | 1 | return false; | |
| 13364 | } | ||
| 13365 | } | ||
| 13366 | |||
| 13367 | /* Validate autoextend_size attribute value. */ | ||
| 13368 |
4/4✓ Branch 0 taken 5425 times.
✓ Branch 1 taken 407380 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 412791 times.
|
418230 | if (m_create_info->m_implicit_tablespace_autoextend_size > 0 && |
| 13369 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5411 times.
|
5425 | validate_autoextend_size_value( |
| 13370 |
1/2✓ Branch 0 taken 5425 times.
✗ Branch 1 not taken.
|
5425 | m_create_info->m_implicit_tablespace_autoextend_size) != |
| 13371 | DB_SUCCESS) { | ||
| 13372 | 14 | return false; | |
| 13373 | } | ||
| 13374 | 412791 | return true; | |
| 13375 | } | ||
| 13376 | |||
| 13377 |
3/4✓ Branch 0 taken 46018 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
✓ Branch 3 taken 45639 times.
|
46018 | if (m_use_shared_space && !is_general_space) { |
| 13378 |
2/2✓ Branch 0 taken 232 times.
✓ Branch 1 taken 147 times.
|
379 | if (m_create_info->m_implicit_tablespace_autoextend_size_change && |
| 13379 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 231 times.
|
232 | m_create_info->m_implicit_tablespace_autoextend_size > 0) { |
| 13380 | /* AUTOEXTEND_SIZE is not allowed for system tablespace. */ | ||
| 13381 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 13382 | "InnoDB : AUTOEXTEND_SIZE is not accepted" | ||
| 13383 | " for system tablespace.", | ||
| 13384 | MYF(0)); | ||
| 13385 | 1 | return false; | |
| 13386 | } | ||
| 13387 | } | ||
| 13388 | |||
| 13389 | /* ALTER TABLE ... AUTOEXTEND_SIZE is not allowed if the tablespace is | ||
| 13390 | a general tablespace. */ | ||
| 13391 |
5/6✓ Branch 0 taken 45998 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 45634 times.
✓ Branch 3 taken 364 times.
✓ Branch 4 taken 45634 times.
✗ Branch 5 not taken.
|
46017 | if (!is_temp && is_general_space && m_use_shared_space) { |
| 13392 |
2/2✓ Branch 0 taken 28139 times.
✓ Branch 1 taken 17495 times.
|
45634 | if (m_create_info->m_implicit_tablespace_autoextend_size_change && |
| 13393 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 28133 times.
|
28139 | m_create_info->m_implicit_tablespace_autoextend_size > 0) { |
| 13394 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_error(ER_INNODB_INCOMPATIBLE_WITH_TABLESPACE, MYF(0), |
| 13395 | "AUTOEXTEND_SIZE"); | ||
| 13396 | 6 | return false; | |
| 13397 | } | ||
| 13398 | } | ||
| 13399 | |||
| 13400 | /* Validate autoextend_size attribute value. */ | ||
| 13401 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 46009 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46011 times.
|
46013 | if (m_create_info->m_implicit_tablespace_autoextend_size > 0 && |
| 13402 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | validate_autoextend_size_value( |
| 13403 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | m_create_info->m_implicit_tablespace_autoextend_size) != DB_SUCCESS) { |
| 13404 | ✗ | return false; | |
| 13405 | } | ||
| 13406 | |||
| 13407 | /* Name validation should be ensured from the SQL layer. */ | ||
| 13408 |
2/4✓ Branch 0 taken 46011 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46011 times.
|
46011 | ut_ad(0 == validate_tablespace_name(TS_CMD_NOT_DEFINED, |
| 13409 | m_create_info->tablespace)); | ||
| 13410 | |||
| 13411 | /* Look up the tablespace name in the fil_system. */ | ||
| 13412 |
1/2✓ Branch 0 taken 46011 times.
✗ Branch 1 not taken.
|
46011 | space_id_t space_id = fil_space_get_id_by_name(m_create_info->tablespace); |
| 13413 | |||
| 13414 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 46009 times.
|
46011 | if (space_id == SPACE_UNKNOWN) { |
| 13415 | 2 | my_printf_error(ER_TABLESPACE_MISSING, | |
| 13416 | "InnoDB: A general tablespace named" | ||
| 13417 | " `%s` cannot be found.", | ||
| 13418 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | MYF(0), m_create_info->tablespace); |
| 13419 | 2 | return false; | |
| 13420 | } | ||
| 13421 | |||
| 13422 |
3/4✓ Branch 0 taken 46009 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 46007 times.
|
46009 | if (fsp_is_undo_tablespace(space_id)) { |
| 13423 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 13424 | "InnoDB: An undo tablespace cannot contain tables.", | ||
| 13425 | MYF(0)); | ||
| 13426 | |||
| 13427 | 2 | return false; | |
| 13428 | } | ||
| 13429 | |||
| 13430 | /* Cannot add a second table to a file-per-table tablespace. */ | ||
| 13431 |
1/2✓ Branch 0 taken 46007 times.
✗ Branch 1 not taken.
|
46007 | uint32_t fsp_flags = fil_space_get_flags(space_id); |
| 13432 |
2/4✓ Branch 0 taken 46007 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 46007 times.
|
46007 | if (fsp_is_file_per_table(space_id, fsp_flags)) { |
| 13433 | ✗ | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13434 | "InnoDB: Tablespace `%s` is file-per-table so no" | ||
| 13435 | " other table can be added to it.", | ||
| 13436 | ✗ | MYF(0), m_create_info->tablespace); | |
| 13437 | ✗ | return false; | |
| 13438 | } | ||
| 13439 | |||
| 13440 |
1/2✓ Branch 0 taken 46007 times.
✗ Branch 1 not taken.
|
46007 | bool is_create_table = (thd_sql_command(m_thd) == SQLCOM_CREATE_TABLE); |
| 13441 | |||
| 13442 | /* If TABLESPACE=innodb_file_per_table this function is not called | ||
| 13443 | since tablespace_is_shared_space() will return false. Any other | ||
| 13444 | tablespace is incompatible with the DATA DIRECTORY phrase. | ||
| 13445 | On any ALTER TABLE that contains a DATA DIRECTORY, MySQL will issue | ||
| 13446 | a warning like "<DATA DIRECTORY> option ignored." The check below is | ||
| 13447 | needed for CREATE TABLE only. ALTER TABLE may be moving remote | ||
| 13448 | file-per-table table to a general tablespace, in which case the | ||
| 13449 | create_info->data_file_name is not null. */ | ||
| 13450 |
4/4✓ Branch 0 taken 26611 times.
✓ Branch 1 taken 19396 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 26609 times.
|
46007 | if (is_create_table && m_create_info->data_file_name != nullptr && |
| 13451 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | *m_create_info->data_file_name != '\0') { |
| 13452 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 13453 | "InnoDB: DATA DIRECTORY cannot be used" | ||
| 13454 | " with a TABLESPACE assignment.", | ||
| 13455 | MYF(0)); | ||
| 13456 | 2 | return false; | |
| 13457 | } | ||
| 13458 | |||
| 13459 | /* Temp tables only belong in temp tablespaces. */ | ||
| 13460 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 45986 times.
|
46005 | if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 13461 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
|
19 | if (!FSP_FLAGS_GET_TEMPORARY(fsp_flags)) { |
| 13462 | 6 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13463 | "InnoDB: Tablespace `%s` cannot contain" | ||
| 13464 | " TEMPORARY tables.", | ||
| 13465 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | MYF(0), m_create_info->tablespace); |
| 13466 | 6 | return false; | |
| 13467 | } | ||
| 13468 | |||
| 13469 | /* Restrict Compressed Temporary General tablespaces. */ | ||
| 13470 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (m_create_info->key_block_size || |
| 13471 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
|
13 | m_create_info->row_type == ROW_TYPE_COMPRESSED) { |
| 13472 | 1 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13473 | "InnoDB: Temporary tablespace `%s` cannot" | ||
| 13474 | " contain COMPRESSED tables.", | ||
| 13475 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | MYF(0), m_create_info->tablespace); |
| 13476 | 1 | return false; | |
| 13477 | } | ||
| 13478 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 45982 times.
|
45986 | } else if (FSP_FLAGS_GET_TEMPORARY(fsp_flags)) { |
| 13479 | 4 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13480 | "InnoDB: Tablespace `%s` can only contain" | ||
| 13481 | " TEMPORARY tables.", | ||
| 13482 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | MYF(0), m_create_info->tablespace); |
| 13483 | 4 | return false; | |
| 13484 | } | ||
| 13485 | |||
| 13486 | /* Make sure the physical page size of the table matches the | ||
| 13487 | file block size of the tablespace. */ | ||
| 13488 | ulint block_size_needed; | ||
| 13489 | bool table_is_compressed; | ||
| 13490 |
2/2✓ Branch 0 taken 246 times.
✓ Branch 1 taken 45748 times.
|
45994 | if (m_create_info->key_block_size) { |
| 13491 | 246 | block_size_needed = m_create_info->key_block_size * 1024; | |
| 13492 | 246 | table_is_compressed = true; | |
| 13493 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 45740 times.
|
45748 | } else if (m_create_info->row_type == ROW_TYPE_COMPRESSED) { |
| 13494 | 8 | block_size_needed = | |
| 13495 | 8 | std::min(UNIV_PAGE_SIZE / 2, static_cast<ulint>(UNIV_ZIP_SIZE_MAX)); | |
| 13496 | 8 | table_is_compressed = true; | |
| 13497 | } else { | ||
| 13498 | 45740 | block_size_needed = UNIV_PAGE_SIZE; | |
| 13499 | 45740 | table_is_compressed = false; | |
| 13500 | } | ||
| 13501 | |||
| 13502 |
1/2✓ Branch 0 taken 45994 times.
✗ Branch 1 not taken.
|
45994 | const page_size_t page_size(fsp_flags); |
| 13503 | |||
| 13504 | /* The compression code needs some work in order for a general | ||
| 13505 | tablespace to contain both compressed and non-compressed tables | ||
| 13506 | together in the same tablespace. The problem seems to be that | ||
| 13507 | each page is either compressed or not based on the fsp flags, | ||
| 13508 | which is shared by all tables in that general tablespace. */ | ||
| 13509 |
7/8✓ Branch 0 taken 254 times.
✓ Branch 1 taken 45740 times.
✓ Branch 2 taken 254 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✓ Branch 5 taken 185 times.
✓ Branch 6 taken 69 times.
✓ Branch 7 taken 45925 times.
|
45994 | if (table_is_compressed && page_size.physical() == UNIV_PAGE_SIZE) { |
| 13510 | 69 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13511 | "InnoDB: Tablespace `%s` cannot contain a" | ||
| 13512 | " COMPRESSED table", | ||
| 13513 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | MYF(0), m_create_info->tablespace); |
| 13514 | 69 | return false; | |
| 13515 | } | ||
| 13516 | |||
| 13517 |
3/4✓ Branch 0 taken 45925 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✓ Branch 3 taken 45775 times.
|
45925 | if (block_size_needed != page_size.physical()) { |
| 13518 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 13519 | "InnoDB: Tablespace `%s` uses block size %zu" | ||
| 13520 | " and cannot contain a table with physical" | ||
| 13521 | " page size " ULINTPF, | ||
| 13522 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | MYF(0), m_create_info->tablespace, page_size.physical(), |
| 13523 | block_size_needed); | ||
| 13524 | 150 | return false; | |
| 13525 | } | ||
| 13526 | |||
| 13527 | 45775 | return true; | |
| 13528 | } | ||
| 13529 | |||
| 13530 | /** Validate the COPMRESSION option. | ||
| 13531 | @return true if valid, false if not. */ | ||
| 13532 | 835314 | bool create_table_info_t::create_option_compression_is_valid() { | |
| 13533 | dberr_t err; | ||
| 13534 | 835314 | Compression compression; | |
| 13535 | |||
| 13536 |
2/2✓ Branch 0 taken 834836 times.
✓ Branch 1 taken 480 times.
|
835316 | if (m_create_info->compress.length == 0) { |
| 13537 | 834836 | return (true); | |
| 13538 | } | ||
| 13539 | |||
| 13540 |
1/2✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
|
480 | err = Compression::check(m_create_info->compress.str, &compression); |
| 13541 | |||
| 13542 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 473 times.
|
479 | if (err == DB_UNSUPPORTED) { |
| 13543 | 6 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 13544 | ER_UNSUPPORTED_EXTENSION, | ||
| 13545 | "InnoDB: Unsupported compression algorithm '%s'", | ||
| 13546 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | m_create_info->compress.str); |
| 13547 | 6 | return (false); | |
| 13548 | } | ||
| 13549 | |||
| 13550 | /* Allow Compression=NONE on any tablespace or row format. */ | ||
| 13551 |
2/2✓ Branch 0 taken 86 times.
✓ Branch 1 taken 387 times.
|
473 | if (compression.m_type == Compression::NONE) { |
| 13552 | 86 | return (true); | |
| 13553 | } | ||
| 13554 | |||
| 13555 | static char intro[] = "InnoDB: Page Compression is not supported"; | ||
| 13556 | |||
| 13557 |
2/2✓ Branch 0 taken 383 times.
✓ Branch 1 taken 4 times.
|
387 | if (m_create_info->key_block_size != 0 || |
| 13558 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 377 times.
|
383 | m_create_info->row_type == ROW_TYPE_COMPRESSED) { |
| 13559 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 13560 | ER_UNSUPPORTED_EXTENSION, | ||
| 13561 | "%s with row_format=compressed or" | ||
| 13562 | " key_block_size > 0", | ||
| 13563 | intro); | ||
| 13564 | 10 | return (false); | |
| 13565 | } | ||
| 13566 | |||
| 13567 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 372 times.
|
377 | if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 13568 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 13569 | "%s for temporary tables", intro); | ||
| 13570 | 5 | return (false); | |
| 13571 | } | ||
| 13572 | |||
| 13573 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 366 times.
|
372 | if (tablespace_is_general_space(m_create_info)) { |
| 13574 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 13575 | "%s for shared general tablespaces", intro); | ||
| 13576 | 6 | return (false); | |
| 13577 | } | ||
| 13578 | |||
| 13579 | /* The only non-file-per-table tablespace left is the system space. */ | ||
| 13580 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 341 times.
|
366 | if (!m_use_file_per_table) { |
| 13581 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, HA_ERR_UNSUPPORTED, |
| 13582 | "%s for the system tablespace", intro); | ||
| 13583 | 25 | return (false); | |
| 13584 | } | ||
| 13585 | |||
| 13586 | 341 | return (true); | |
| 13587 | } | ||
| 13588 | |||
| 13589 | /** Validate ENCRYPTION option. | ||
| 13590 | @return true if valid, false if not. */ | ||
| 13591 | 458566 | bool create_table_info_t::create_option_encryption_is_valid() const { | |
| 13592 |
2/2✓ Branch 0 taken 105219 times.
✓ Branch 1 taken 353347 times.
|
458566 | if (m_create_info->encrypt_type.length > 0) { |
| 13593 | 105219 | dberr_t err = Encryption::validate(m_create_info->encrypt_type.str); | |
| 13594 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 105220 times.
|
105220 | if (err == DB_UNSUPPORTED) { |
| 13595 | ✗ | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); | |
| 13596 | ✗ | return (false); | |
| 13597 | } | ||
| 13598 | } | ||
| 13599 | |||
| 13600 | bool table_is_keyring = | ||
| 13601 | 458567 | Encryption::is_keyring(m_create_info->encrypt_type.str); | |
| 13602 | |||
| 13603 |
3/4✓ Branch 0 taken 77 times.
✓ Branch 1 taken 458490 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
|
458567 | if (table_is_keyring && !m_allow_file_per_table) { |
| 13604 | ✗ | my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | |
| 13605 | "InnoDB: KEYRING requires innodb_file_per_table.", MYF(0)); | ||
| 13606 | ✗ | return (false); | |
| 13607 | } | ||
| 13608 | |||
| 13609 |
2/2✓ Branch 0 taken 4902 times.
✓ Branch 1 taken 453588 times.
|
458490 | if (!table_is_keyring && |
| 13610 |
4/6✓ Branch 0 taken 458490 times.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4902 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 458567 times.
|
917057 | Encryption::is_master_key_encryption(m_create_info->encrypt_type.str) && |
| 13611 | 4902 | Encryption::is_online_encryption_on()) { | |
| 13612 | ✗ | my_printf_error(ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | |
| 13613 | "InnoDB: ENCRYPTED='Y' not supported for table because " | ||
| 13614 | "online encryption to KEYRING is turned ON.", | ||
| 13615 | MYF(0)); | ||
| 13616 | ✗ | return (false); | |
| 13617 | } | ||
| 13618 | |||
| 13619 | /* Currently we do not support keyring encryption for | ||
| 13620 | spatial indexes thus do not allow creating table with forced | ||
| 13621 | encryption */ | ||
| 13622 | |||
| 13623 |
2/2✓ Branch 0 taken 85 times.
✓ Branch 1 taken 458482 times.
|
458567 | if (Encryption::should_be_keyring_encrypted( |
| 13624 | 458567 | m_create_info->explicit_encryption, | |
| 13625 | 458567 | m_create_info->encrypt_type.str)) { | |
| 13626 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 85 times.
|
126 | for (ulint i = 0; i < m_form->s->keys; i++) { |
| 13627 | 41 | const KEY *key = m_form->key_info + i; | |
| 13628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (key->flags & HA_SPATIAL) { |
| 13629 | ✗ | my_printf_error( | |
| 13630 | ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | ||
| 13631 | "InnoDB: ENCRYPTED='KEYRING' not supported for table because " | ||
| 13632 | "it contains spatial index.", | ||
| 13633 | MYF(0)); | ||
| 13634 | ✗ | return (false); | |
| 13635 | } | ||
| 13636 | } | ||
| 13637 | } | ||
| 13638 | |||
| 13639 | const bool table_is_encrypted = | ||
| 13640 | 458567 | !Encryption::is_none(m_create_info->encrypt_type.str); | |
| 13641 | |||
| 13642 | ulint space_id; | ||
| 13643 |
2/2✓ Branch 0 taken 45775 times.
✓ Branch 1 taken 412792 times.
|
458567 | if (m_use_shared_space) { |
| 13644 | 45775 | space_id = fil_space_get_id_by_name(m_create_info->tablespace); | |
| 13645 |
2/2✓ Branch 0 taken 228843 times.
✓ Branch 1 taken 183949 times.
|
412792 | } else if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { |
| 13646 | 228843 | space_id = srv_tmp_space.space_id(); | |
| 13647 |
2/2✓ Branch 0 taken 4529 times.
✓ Branch 1 taken 179420 times.
|
183949 | } else if (!m_use_file_per_table) { |
| 13648 | 4529 | space_id = TRX_SYS_SPACE; | |
| 13649 | } else { | ||
| 13650 | 179420 | return (true); | |
| 13651 | } | ||
| 13652 | |||
| 13653 | 279147 | fil_space_t *space = fil_space_get(space_id); | |
| 13654 | 279147 | const auto fsp_flags = space->flags; | |
| 13655 | |||
| 13656 | 279147 | const bool tablespace_is_encrypted = FSP_FLAGS_GET_ENCRYPTION(fsp_flags); | |
| 13657 | 279147 | const char *const tablespace_name = | |
| 13658 |
2/2✓ Branch 0 taken 48863 times.
✓ Branch 1 taken 230284 times.
|
279147 | m_create_info->tablespace ? m_create_info->tablespace : space->name; |
| 13659 | |||
| 13660 |
3/4✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 277893 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1254 times.
|
279147 | if (table_is_encrypted && !tablespace_is_encrypted) { |
| 13661 | ✗ | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13662 | "InnoDB: Tablespace `%s` cannot contain an" | ||
| 13663 | " ENCRYPTED table.", | ||
| 13664 | MYF(0), tablespace_name); | ||
| 13665 | ✗ | return (false); | |
| 13666 | } | ||
| 13667 | |||
| 13668 | 279147 | return (true); | |
| 13669 | } | ||
| 13670 | |||
| 13671 | /** Validate the create options. Check that the options KEY_BLOCK_SIZE, | ||
| 13672 | ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE are compatible with | ||
| 13673 | each other and other settings. These CREATE OPTIONS are not validated | ||
| 13674 | here unless innodb_strict_mode is on. With strict mode, this function | ||
| 13675 | will report each problem it finds using a custom message with error | ||
| 13676 | code ER_ILLEGAL_HA_CREATE_OPTION, not its built-in message. | ||
| 13677 | @return NULL if valid, string name of bad option if not. */ | ||
| 13678 | 458916 | const char *create_table_info_t::create_options_are_invalid() { | |
| 13679 | 458916 | bool has_key_block_size = (m_create_info->key_block_size != 0); | |
| 13680 | 458916 | bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 13681 | |||
| 13682 | 458916 | const char *ret = nullptr; | |
| 13683 | 458916 | enum row_type row_format = m_create_info->row_type; | |
| 13684 | |||
| 13685 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 458917 times.
|
458916 | ut_ad(m_thd != nullptr); |
| 13686 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 458917 times.
|
458917 | ut_ad(m_create_info != nullptr); |
| 13687 | |||
| 13688 | /* The TABLESPACE designation on a CREATE TABLE is not subject to | ||
| 13689 | non-strict-mode. If it is incorrect or is incompatible with other | ||
| 13690 | options, then we will return an error. Make sure the tablespace exists | ||
| 13691 | and is compatible with this table */ | ||
| 13692 |
2/2✓ Branch 0 taken 350 times.
✓ Branch 1 taken 458566 times.
|
458917 | if (!create_option_tablespace_is_valid()) { |
| 13693 | 350 | return ("TABLESPACE"); | |
| 13694 | } | ||
| 13695 | |||
| 13696 | /* Validate encryption parameter even if strict_mode is OFF. */ | ||
| 13697 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 458567 times.
|
458566 | if (!create_option_encryption_is_valid()) return ("ENCRYPTION"); |
| 13698 | |||
| 13699 | /* If innodb_strict_mode is not set don't do any more validation. | ||
| 13700 | Also, if this table is being put into a shared general tablespace | ||
| 13701 | we ALWAYS act like strict mode is ON. | ||
| 13702 | Or if caller explicitly asks for skipping strict mode check (if | ||
| 13703 | tablespace is not a shared general tablespace), then skip */ | ||
| 13704 |
8/8✓ Branch 0 taken 412792 times.
✓ Branch 1 taken 45775 times.
✓ Branch 2 taken 411491 times.
✓ Branch 3 taken 1301 times.
✓ Branch 4 taken 50321 times.
✓ Branch 5 taken 361170 times.
✓ Branch 6 taken 51622 times.
✓ Branch 7 taken 406945 times.
|
458567 | if (!m_use_shared_space && (!(THDVAR(m_thd, strict_mode)) || skip_strict())) { |
| 13705 | 51622 | return (nullptr); | |
| 13706 | } | ||
| 13707 | |||
| 13708 | /* Check if a non-zero KEY_BLOCK_SIZE was specified. */ | ||
| 13709 |
2/2✓ Branch 0 taken 384 times.
✓ Branch 1 taken 406561 times.
|
406945 | if (has_key_block_size) { |
| 13710 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 374 times.
|
384 | if (is_temp) { |
| 13711 | 10 | my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0)); | |
| 13712 | 10 | return ("KEY_BLOCK_SIZE"); | |
| 13713 | } | ||
| 13714 | |||
| 13715 |
2/2✓ Branch 0 taken 365 times.
✓ Branch 1 taken 9 times.
|
374 | switch (m_create_info->key_block_size) { |
| 13716 | ulint kbs_max; | ||
| 13717 | 365 | case 1: | |
| 13718 | case 2: | ||
| 13719 | case 4: | ||
| 13720 | case 8: | ||
| 13721 | case 16: | ||
| 13722 | /* The maximum KEY_BLOCK_SIZE (KBS) is | ||
| 13723 | UNIV_PAGE_SIZE_MAX. But if UNIV_PAGE_SIZE is | ||
| 13724 | smaller than UNIV_PAGE_SIZE_MAX, the maximum | ||
| 13725 | KBS is also smaller. */ | ||
| 13726 | 730 | kbs_max = std::min(1 << (UNIV_PAGE_SSIZE_MAX - 1), | |
| 13727 | 365 | 1 << (PAGE_ZIP_SSIZE_MAX - 1)); | |
| 13728 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 356 times.
|
365 | if (m_create_info->key_block_size > kbs_max) { |
| 13729 | 9 | push_warning_printf( | |
| 13730 | m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13731 | "InnoDB: KEY_BLOCK_SIZE=%" PRIu32 " cannot be larger than %ld.", | ||
| 13732 | 9 | m_create_info->key_block_size, kbs_max); | |
| 13733 | 9 | ret = "KEY_BLOCK_SIZE"; | |
| 13734 | } | ||
| 13735 | |||
| 13736 | /* The following checks do not appy to shared tablespaces */ | ||
| 13737 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 305 times.
|
365 | if (m_use_shared_space) { |
| 13738 | 60 | break; | |
| 13739 | } | ||
| 13740 | |||
| 13741 | /* Valid KEY_BLOCK_SIZE, check its dependencies. */ | ||
| 13742 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 294 times.
|
305 | if (!m_allow_file_per_table) { |
| 13743 | 11 | push_warning(m_thd, Sql_condition::SL_WARNING, | |
| 13744 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13745 | "InnoDB: KEY_BLOCK_SIZE requires" | ||
| 13746 | " innodb_file_per_table."); | ||
| 13747 | 11 | ret = "KEY_BLOCK_SIZE"; | |
| 13748 | } | ||
| 13749 | 305 | break; | |
| 13750 | 9 | default: | |
| 13751 | 9 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 13752 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13753 | "InnoDB: invalid KEY_BLOCK_SIZE = %" PRIu32 | ||
| 13754 | ". Valid values are [1, 2, 4, 8, 16]", | ||
| 13755 | 9 | m_create_info->key_block_size); | |
| 13756 | 9 | ret = "KEY_BLOCK_SIZE"; | |
| 13757 | 9 | break; | |
| 13758 | } | ||
| 13759 | } | ||
| 13760 | |||
| 13761 | /* Check for a valid InnoDB ROW_FORMAT specifier and | ||
| 13762 | other incompatibilities. */ | ||
| 13763 |
5/5✓ Branch 0 taken 402 times.
✓ Branch 1 taken 39952 times.
✓ Branch 2 taken 366573 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 1 times.
|
406935 | switch (row_format) { |
| 13764 | 402 | case ROW_TYPE_COMPRESSED: | |
| 13765 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 379 times.
|
402 | if (is_temp) { |
| 13766 | 23 | my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, MYF(0)); | |
| 13767 | 23 | return ("ROW_FORMAT"); | |
| 13768 | } | ||
| 13769 |
4/4✓ Branch 0 taken 343 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 341 times.
|
379 | if (!m_use_shared_space && !m_allow_file_per_table) { |
| 13770 | 2 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 13771 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13772 | "InnoDB: %s requires innodb_file_per_table.", | ||
| 13773 | get_row_format_name(row_format)); | ||
| 13774 | 2 | ret = "ROW_FORMAT"; | |
| 13775 | } | ||
| 13776 | 379 | break; | |
| 13777 | 39952 | case ROW_TYPE_DYNAMIC: | |
| 13778 | case ROW_TYPE_COMPACT: | ||
| 13779 | case ROW_TYPE_REDUNDANT: | ||
| 13780 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 39930 times.
|
39952 | if (has_key_block_size) { |
| 13781 | 22 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 13782 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13783 | "InnoDB: cannot specify %s" | ||
| 13784 | " with KEY_BLOCK_SIZE.", | ||
| 13785 | get_row_format_name(row_format)); | ||
| 13786 | 22 | ret = "KEY_BLOCK_SIZE"; | |
| 13787 | } | ||
| 13788 | 39952 | break; | |
| 13789 | 366573 | case ROW_TYPE_DEFAULT: | |
| 13790 | 366573 | break; | |
| 13791 | 7 | case ROW_TYPE_FIXED: | |
| 13792 | case ROW_TYPE_PAGED: | ||
| 13793 | case ROW_TYPE_NOT_USED: | ||
| 13794 | 7 | push_warning(m_thd, Sql_condition::SL_WARNING, | |
| 13795 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13796 | "InnoDB: invalid ROW_FORMAT specifier."); | ||
| 13797 | 7 | ret = "ROW_TYPE"; | |
| 13798 | 7 | break; | |
| 13799 | } | ||
| 13800 | |||
| 13801 | 832916 | if (m_create_info->data_file_name != nullptr && | |
| 13802 |
8/8✓ Branch 0 taken 19092 times.
✓ Branch 1 taken 387820 times.
✓ Branch 2 taken 497 times.
✓ Branch 3 taken 18595 times.
✓ Branch 4 taken 417 times.
✓ Branch 5 taken 80 times.
✓ Branch 6 taken 25 times.
✓ Branch 7 taken 406887 times.
|
407329 | *m_create_info->data_file_name != '\0' && m_table_name != nullptr && |
| 13803 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 392 times.
|
417 | !create_option_data_directory_is_valid()) { |
| 13804 | 25 | ret = "DATA DIRECTORY"; | |
| 13805 | } | ||
| 13806 | |||
| 13807 | /* Do not allow INDEX_DIRECTORY */ | ||
| 13808 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 406908 times.
|
406912 | if (m_create_info->index_file_name) { |
| 13809 | 4 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 13810 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 13811 | "InnoDB: INDEX DIRECTORY is not supported"); | ||
| 13812 | 4 | ret = "INDEX DIRECTORY"; | |
| 13813 | } | ||
| 13814 | |||
| 13815 | /* Don't support compressed table when page size > 16k. */ | ||
| 13816 |
4/4✓ Branch 0 taken 406537 times.
✓ Branch 1 taken 375 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 406381 times.
|
406912 | if ((has_key_block_size || row_format == ROW_TYPE_COMPRESSED) && |
| 13817 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 518 times.
|
531 | UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) { |
| 13818 | 13 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | |
| 13819 | "InnoDB: Cannot create a COMPRESSED table" | ||
| 13820 | " when innodb_page_size > 16k."); | ||
| 13821 | |||
| 13822 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
|
13 | if (has_key_block_size) { |
| 13823 | 8 | ret = "KEY_BLOCK_SIZE"; | |
| 13824 | } else { | ||
| 13825 | 5 | ret = "ROW_TYPE"; | |
| 13826 | } | ||
| 13827 | } | ||
| 13828 | |||
| 13829 | /* Validate the page compression parameter. */ | ||
| 13830 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 406869 times.
|
406912 | if (!create_option_compression_is_valid()) { |
| 13831 | 42 | return ("COMPRESSION"); | |
| 13832 | } | ||
| 13833 | |||
| 13834 | /* Check the encryption option. */ | ||
| 13835 |
4/4✓ Branch 0 taken 406778 times.
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 54495 times.
✓ Branch 3 taken 352283 times.
|
406869 | if (ret == nullptr && m_create_info->encrypt_type.str != nullptr) { |
| 13836 | dberr_t err; | ||
| 13837 | |||
| 13838 | 54495 | err = Encryption::validate(m_create_info->encrypt_type.str); | |
| 13839 | |||
| 13840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54496 times.
|
54495 | if (err == DB_UNSUPPORTED) { |
| 13841 | ✗ | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); | |
| 13842 | ✗ | ret = "ENCRYPTION"; | |
| 13843 | } | ||
| 13844 | } | ||
| 13845 | |||
| 13846 | 406870 | return (ret); | |
| 13847 | } | ||
| 13848 | |||
| 13849 | 226313 | void ha_innobase::adjust_encryption_key_id(HA_CREATE_INFO *create_info, | |
| 13850 | dd::Properties *options) noexcept { | ||
| 13851 |
2/2✓ Branch 0 taken 226310 times.
✓ Branch 1 taken 3 times.
|
226313 | if (false == create_info->was_encryption_key_id_set) { |
| 13852 |
2/2✓ Branch 0 taken 79 times.
✓ Branch 1 taken 226231 times.
|
226310 | if (Encryption::should_be_keyring_encrypted( |
| 13853 | 226310 | create_info->explicit_encryption, create_info->encrypt_type.str)) { | |
| 13854 | 79 | create_info->encryption_key_id = | |
| 13855 | 79 | THDVAR(current_thd, default_encryption_key_id); | |
| 13856 | } | ||
| 13857 | } else { | ||
| 13858 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (options && (create_info->tablespace == nullptr || |
| 13859 | ✗ | strcmp(create_info->tablespace, | |
| 13860 | dict_sys_t::s_file_per_table_name) == 0)) { | ||
| 13861 | 3 | options->set("encryption_key_id", create_info->encryption_key_id); | |
| 13862 | } | ||
| 13863 | |||
| 13864 |
3/6✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
|
6 | if (Encryption::is_master_key_encryption(create_info->encrypt_type.str) || |
| 13865 | 3 | Encryption::none_explicitly_specified(create_info->explicit_encryption, | |
| 13866 | 3 | create_info->encrypt_type.str)) { | |
| 13867 | // if it is encrypted table with Master key encryption or marked as not to | ||
| 13868 | // be encrypted and alter table does not have ENCRYPTION_KEY_ID - mark | ||
| 13869 | // encryption key id as not set. | ||
| 13870 | |||
| 13871 | ✗ | push_warning_printf( | |
| 13872 | ✗ | current_thd, Sql_condition::SL_WARNING, HA_WRONG_CREATE_OPTION, | |
| 13873 | ✗ | Encryption::none_explicitly_specified( | |
| 13874 | ✗ | create_info->explicit_encryption, create_info->encrypt_type.str) | |
| 13875 | ? "InnoDB: Ignored ENCRYPTION_KEY_ID %u when " | ||
| 13876 | "encryption is disabled." | ||
| 13877 | : "InnoDB: Ignored ENCRYPTION_KEY_ID %u when " | ||
| 13878 | "Master Key encryption is enabled.", | ||
| 13879 | create_info->encryption_key_id); | ||
| 13880 | ✗ | create_info->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY; | |
| 13881 | ✗ | create_info->was_encryption_key_id_set = false; | |
| 13882 | ✗ | options->remove("encryption_key_id"); | |
| 13883 | } | ||
| 13884 | } | ||
| 13885 | 226313 | } | |
| 13886 | |||
| 13887 | /** Adjust encryption options. | ||
| 13888 | @param[in,out] create_info Additional create information. | ||
| 13889 | @param[in,out] table_def dd::Table object to be modified.*/ | ||
| 13890 | 407290 | void ha_innobase::adjust_encryption_options(HA_CREATE_INFO *create_info, | |
| 13891 | dd::Table *table_def) noexcept { | ||
| 13892 | 407290 | bool is_intrinsic = | |
| 13893 | 407290 | (create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) != 0; | |
| 13894 | |||
| 13895 |
2/2✓ Branch 0 taken 182646 times.
✓ Branch 1 taken 224644 times.
|
407290 | if (is_intrinsic) { |
| 13896 | 182646 | return; | |
| 13897 | } | ||
| 13898 | |||
| 13899 | #ifdef UNIV_DEBUG | ||
| 13900 | // check that create_info->explicit_encryption is in sync with | ||
| 13901 | // DD's explicit_encryption | ||
| 13902 |
2/2✓ Branch 0 taken 19877 times.
✓ Branch 1 taken 204767 times.
|
224644 | if (create_info->explicit_encryption) { |
| 13903 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19877 times.
|
19877 | ut_ad(table_def->options().exists("explicit_encryption")); |
| 13904 | 19877 | bool explicit_encryption{false}; | |
| 13905 | 19877 | table_def->options().get("explicit_encryption", &explicit_encryption); | |
| 13906 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19877 times.
|
19877 | ut_ad(explicit_encryption); |
| 13907 | } | ||
| 13908 | #endif /* UNIV_DEBUG */ | ||
| 13909 | |||
| 13910 | 224644 | bool is_tmp = (create_info->options & HA_LEX_CREATE_TMP_TABLE) != 0; | |
| 13911 | |||
| 13912 |
2/2✓ Branch 0 taken 46221 times.
✓ Branch 1 taken 178423 times.
|
224644 | if (is_tmp) { |
| 13913 | 46221 | return; | |
| 13914 | } | ||
| 13915 | |||
| 13916 |
1/2✓ Branch 0 taken 178423 times.
✗ Branch 1 not taken.
|
356846 | adjust_encryption_key_id(create_info, |
| 13917 | 178423 | table_def ? &(table_def->options()) : nullptr); | |
| 13918 | } | ||
| 13919 | |||
| 13920 | /** Update create_info. Used in SHOW CREATE TABLE et al. */ | ||
| 13921 | |||
| 13922 | 101119 | void ha_innobase::update_create_info( | |
| 13923 | HA_CREATE_INFO *create_info) /*!< in/out: create info */ | ||
| 13924 | { | ||
| 13925 |
2/2✓ Branch 0 taken 100946 times.
✓ Branch 1 taken 173 times.
|
101119 | if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) { |
| 13926 | 100946 | info(HA_STATUS_AUTO); | |
| 13927 | 100946 | create_info->auto_increment_value = stats.auto_increment_value; | |
| 13928 | } | ||
| 13929 | |||
| 13930 | /* Update the DATA DIRECTORY name. */ | ||
| 13931 | 101119 | dd_get_and_save_data_dir_path<dd::Table>(m_prebuilt->table, nullptr, false); | |
| 13932 | |||
| 13933 |
2/2✓ Branch 0 taken 195 times.
✓ Branch 1 taken 100924 times.
|
101119 | if (m_prebuilt->table->data_dir_path != nullptr) { |
| 13934 | 195 | create_info->data_file_name = m_prebuilt->table->data_dir_path; | |
| 13935 | } | ||
| 13936 | |||
| 13937 | /* Update the TABLESPACE name from the Data Dictionary. */ | ||
| 13938 | 101119 | dict_get_and_save_space_name(m_prebuilt->table); | |
| 13939 | |||
| 13940 | /* Put this tablespace name into the create_info structure so that | ||
| 13941 | SHOW CREATE TABLE will display TABLESPACE=name. This also affects | ||
| 13942 | an ALTER TABLE which must know the current TABLESPACE so that the | ||
| 13943 | table will stay there. */ | ||
| 13944 |
4/4✓ Branch 0 taken 29461 times.
✓ Branch 1 taken 71658 times.
✓ Branch 2 taken 2316 times.
✓ Branch 3 taken 98803 times.
|
130580 | if (m_prebuilt->table->tablespace != nullptr && |
| 13945 |
2/2✓ Branch 0 taken 2316 times.
✓ Branch 1 taken 27145 times.
|
29461 | create_info->tablespace == nullptr) { |
| 13946 | 2316 | create_info->tablespace = m_prebuilt->table->tablespace; | |
| 13947 | } | ||
| 13948 | 101119 | } | |
| 13949 | |||
| 13950 | /** Initialize the table FTS stopword list | ||
| 13951 | @return true if success */ | ||
| 13952 | 768 | bool innobase_fts_load_stopword( | |
| 13953 | dict_table_t *table, /*!< in: Table has the FTS */ | ||
| 13954 | trx_t *trx, /*!< in: transaction */ | ||
| 13955 | THD *thd) /*!< in: current thread */ | ||
| 13956 | { | ||
| 13957 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 768 times.
|
768 | ut_ad(!dict_sys_mutex_own()); |
| 13958 | |||
| 13959 | 2304 | return (fts_load_stopword(table, trx, innobase_server_stopword_table, | |
| 13960 | 768 | THDVAR(thd, ft_user_stopword_table), | |
| 13961 | 1536 | THDVAR(thd, ft_enable_stopword), false)); | |
| 13962 | } | ||
| 13963 | |||
| 13964 | 12008 | static bool innobase_ddse_dict_init( | |
| 13965 | dict_init_mode_t dict_init_mode, uint, List<const dd::Object_table> *tables, | ||
| 13966 | List<const Plugin_tablespace> *tablespaces) { | ||
| 13967 |
1/2✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
|
12008 | DBUG_TRACE; |
| 13968 | |||
| 13969 |
8/16✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12008 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12008 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12008 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12008 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12008 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12008 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 12008 times.
✗ Branch 15 not taken.
|
12008 | LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_START_INITIALIZE); |
| 13970 | |||
| 13971 |
2/4✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12008 times.
✗ Branch 3 not taken.
|
12008 | assert(tables && tables->is_empty()); |
| 13972 |
2/4✓ Branch 0 taken 12008 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12008 times.
✗ Branch 3 not taken.
|
12008 | assert(tablespaces && tablespaces->is_empty()); |
| 13973 | |||
| 13974 |
2/2✓ Branch 0 taken 11934 times.
✓ Branch 1 taken 74 times.
|
12008 | if (dblwr::is_enabled()) { |
| 13975 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 11926 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
11934 | if (innobase_doublewrite_dir != nullptr && *innobase_doublewrite_dir != 0) { |
| 13976 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | dblwr::dir.assign(innobase_doublewrite_dir); |
| 13977 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | switch (dblwr::dir.front()) { |
| 13978 | ✗ | case '#': | |
| 13979 | case '.': | ||
| 13980 | ✗ | break; | |
| 13981 | 8 | default: | |
| 13982 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (!Fil_path::is_absolute_path(dblwr::dir)) { |
| 13983 | ✗ | dblwr::dir.insert(0, "#"); | |
| 13984 | } | ||
| 13985 | } | ||
| 13986 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | ib::info(ER_IB_MSG_DBLWR_1325) |
| 13987 |
3/6✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
16 | << "Using " << dblwr::dir << " as doublewrite directory"; |
| 13988 | } else { | ||
| 13989 |
1/2✓ Branch 0 taken 11926 times.
✗ Branch 1 not taken.
|
11926 | dblwr::dir.assign("."); |
| 13990 | } | ||
| 13991 |
2/4✓ Branch 0 taken 11934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11934 times.
✗ Branch 3 not taken.
|
11934 | ib::info(ER_IB_MSG_DBLWR_1304) << "Atomic write enabled"; |
| 13992 | } else { | ||
| 13993 |
2/4✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
|
74 | ib::info(ER_IB_MSG_DBLWR_1305) << "Atomic write disabled"; |
| 13994 | } | ||
| 13995 | |||
| 13996 | 12008 | bool is_dd_encrypted{false}; | |
| 13997 | |||
| 13998 |
3/4✓ Branch 0 taken 12007 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 11920 times.
|
12008 | if (innobase_init_files(dict_init_mode, tablespaces, is_dd_encrypted)) { |
| 13999 | 87 | return true; | |
| 14000 | } | ||
| 14001 | |||
| 14002 | /* Instantiate table defs only if we are successful so far. */ | ||
| 14003 | dd::Object_table *innodb_dynamic_metadata = | ||
| 14004 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | dd::Object_table::create_object_table(); |
| 14005 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | innodb_dynamic_metadata->set_hidden(true); |
| 14006 | dd::Object_table_definition *def = | ||
| 14007 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | innodb_dynamic_metadata->target_table_definition(); |
| 14008 |
2/4✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
|
11920 | def->set_table_name("innodb_dynamic_metadata"); |
| 14009 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(0, "table_id", "table_id BIGINT UNSIGNED NOT NULL"); |
| 14010 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(1, "version", "version BIGINT UNSIGNED NOT NULL"); |
| 14011 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(2, "metadata", "metadata BLOB NOT NULL"); |
| 14012 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_index(0, "index_pk", "PRIMARY KEY (table_id)"); |
| 14013 | /* Options and tablespace are set at the SQL layer. */ | ||
| 14014 | |||
| 14015 | /* Changing these values would change the specification of innodb statistics | ||
| 14016 | tables. */ | ||
| 14017 | static constexpr size_t DB_NAME_FIELD_SIZE = 64; | ||
| 14018 | static constexpr size_t TABLE_NAME_FIELD_SIZE = 199; | ||
| 14019 | |||
| 14020 | static_assert(DB_NAME_FIELD_SIZE == dict_name::MAX_DB_CHAR_LEN, | ||
| 14021 | "dict_name::MAX_DB_CHAR_LEN mismatch with db column"); | ||
| 14022 | |||
| 14023 | static_assert(TABLE_NAME_FIELD_SIZE == dict_name::MAX_TABLE_CHAR_LEN, | ||
| 14024 | "dict_name::MAX_TABLE_CHAR_LEN mismatch with table column"); | ||
| 14025 | |||
| 14026 | /* Set length for database name field. */ | ||
| 14027 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
23840 | std::ostringstream db_name_field; |
| 14028 |
2/4✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
|
11920 | db_name_field << "database_name VARCHAR(" << DB_NAME_FIELD_SIZE |
| 14029 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | << ") NOT NULL"; |
| 14030 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
23840 | std::string db_field = db_name_field.str(); |
| 14031 | |||
| 14032 | /* Set length for table name field. */ | ||
| 14033 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
23840 | std::ostringstream table_name_field; |
| 14034 |
2/4✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
|
11920 | table_name_field << "table_name VARCHAR(" << TABLE_NAME_FIELD_SIZE |
| 14035 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | << ") NOT NULL"; |
| 14036 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | std::string table_field = table_name_field.str(); |
| 14037 | |||
| 14038 | dd::Object_table *innodb_table_stats = | ||
| 14039 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | dd::Object_table::create_object_table(); |
| 14040 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | innodb_table_stats->set_hidden(false); |
| 14041 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | def = innodb_table_stats->target_table_definition(); |
| 14042 |
2/4✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
|
11920 | def->set_table_name("innodb_table_stats"); |
| 14043 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(0, "database_name", db_field.c_str()); |
| 14044 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(1, "table_name", table_field.c_str()); |
| 14045 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(2, "last_update", |
| 14046 | "last_update TIMESTAMP NOT NULL \n" | ||
| 14047 | " DEFAULT CURRENT_TIMESTAMP \n" | ||
| 14048 | " ON UPDATE CURRENT_TIMESTAMP"); | ||
| 14049 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(3, "n_rows", "n_rows BIGINT UNSIGNED NOT NULL"); |
| 14050 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(4, "clustered_index_size", |
| 14051 | "clustered_index_size BIGINT UNSIGNED NOT NULL"); | ||
| 14052 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(5, "sum_of_other_index_sizes", |
| 14053 | "sum_of_other_index_sizes BIGINT UNSIGNED NOT NULL"); | ||
| 14054 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_index(0, "index_pk", "PRIMARY KEY (database_name, table_name)"); |
| 14055 | /* Options and tablespace are set at the SQL layer. */ | ||
| 14056 | |||
| 14057 | dd::Object_table *innodb_index_stats = | ||
| 14058 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | dd::Object_table::create_object_table(); |
| 14059 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | innodb_index_stats->set_hidden(false); |
| 14060 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | def = innodb_index_stats->target_table_definition(); |
| 14061 |
2/4✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
|
11920 | def->set_table_name("innodb_index_stats"); |
| 14062 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(0, "database_name", db_field.c_str()); |
| 14063 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(1, "table_name", table_field.c_str()); |
| 14064 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(2, "index_name", "index_name VARCHAR(64) NOT NULL"); |
| 14065 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(3, "last_update", |
| 14066 | "last_update TIMESTAMP NOT NULL" | ||
| 14067 | " DEFAULT CURRENT_TIMESTAMP" | ||
| 14068 | " ON UPDATE CURRENT_TIMESTAMP"); | ||
| 14069 | /* | ||
| 14070 | There are at least: stat_name='size' | ||
| 14071 | stat_name='n_leaf_pages' | ||
| 14072 | stat_name='n_diff_pfx%' | ||
| 14073 | */ | ||
| 14074 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(4, "stat_name", "stat_name VARCHAR(64) NOT NULL"); |
| 14075 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(5, "stat_value", "stat_value BIGINT UNSIGNED NOT NULL"); |
| 14076 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(6, "sample_size", "sample_size BIGINT UNSIGNED"); |
| 14077 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(7, "stat_description", |
| 14078 | "stat_description VARCHAR(1024) NOT NULL"); | ||
| 14079 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_index(0, "index_pk", |
| 14080 | "PRIMARY KEY (database_name, table_name, " | ||
| 14081 | "index_name, stat_name)"); | ||
| 14082 | /* Options and tablespace are set at the SQL layer. */ | ||
| 14083 | |||
| 14084 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | dd::Object_table *innodb_ddl_log = dd::Object_table::create_object_table(); |
| 14085 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | innodb_ddl_log->set_hidden(true); |
| 14086 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | def = innodb_ddl_log->target_table_definition(); |
| 14087 |
2/4✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
|
11920 | def->set_table_name("innodb_ddl_log"); |
| 14088 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(0, "id", "id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT"); |
| 14089 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(1, "thread_id", "thread_id BIGINT UNSIGNED NOT NULL"); |
| 14090 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(2, "type", "type INT UNSIGNED NOT NULL"); |
| 14091 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(3, "space_id", "space_id INT UNSIGNED"); |
| 14092 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(4, "page_no", "page_no INT UNSIGNED"); |
| 14093 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(5, "index_id", "index_id BIGINT UNSIGNED"); |
| 14094 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(6, "table_id", "table_id BIGINT UNSIGNED"); |
| 14095 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(7, "old_file_path", |
| 14096 | "old_file_path VARCHAR(512) COLLATE UTF8_BIN"); | ||
| 14097 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_field(8, "new_file_path", |
| 14098 | "new_file_path VARCHAR(512) COLLATE UTF8_BIN"); | ||
| 14099 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_index(0, "index_pk", "PRIMARY KEY(id)"); |
| 14100 |
3/6✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
|
11920 | def->add_index(1, "index_k_thread_id", "KEY(thread_id)"); |
| 14101 | /* Options and tablespace are set at the SQL layer. */ | ||
| 14102 | |||
| 14103 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 11869 times.
|
11920 | if (is_dd_encrypted) { |
| 14104 |
1/2✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
|
51 | innodb_dynamic_metadata->set_target_encrypted(); |
| 14105 |
1/2✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
|
51 | innodb_table_stats->set_target_encrypted(); |
| 14106 |
1/2✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
|
51 | innodb_index_stats->set_target_encrypted(); |
| 14107 |
1/2✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
|
51 | innodb_ddl_log->set_target_encrypted(); |
| 14108 | } | ||
| 14109 | |||
| 14110 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | tables->push_back(innodb_dynamic_metadata); |
| 14111 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | tables->push_back(innodb_table_stats); |
| 14112 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | tables->push_back(innodb_index_stats); |
| 14113 |
1/2✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
|
11920 | tables->push_back(innodb_ddl_log); |
| 14114 | |||
| 14115 |
8/16✓ Branch 0 taken 11920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11920 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11920 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11920 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11920 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11920 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11920 times.
✗ Branch 15 not taken.
|
11920 | LogErr(SYSTEM_LEVEL, ER_IB_MSG_INNODB_END_INITIALIZE); |
| 14116 | |||
| 14117 | 11920 | return false; | |
| 14118 | 12007 | } | |
| 14119 | |||
| 14120 | /** Initialize the set of hard coded DD table ids. | ||
| 14121 | @param[in] dd_table_id Table id of DD table. */ | ||
| 14122 | 406345 | static void innobase_dict_register_dd_table_id(dd::Object_id dd_table_id) { | |
| 14123 | 406345 | dict_sys_t::s_dd_table_ids.insert(dd_table_id); | |
| 14124 | 406345 | } | |
| 14125 | |||
| 14126 | /** Parse the table name into normal name and remote path if needed. | ||
| 14127 | @param[in] name Table name (db/table or full path). | ||
| 14128 | @return 0 if successful, otherwise, error number */ | ||
| 14129 | 432840 | int create_table_info_t::parse_table_name(const char *name) { | |
| 14130 |
1/2✓ Branch 0 taken 432841 times.
✗ Branch 1 not taken.
|
432840 | DBUG_TRACE; |
| 14131 | |||
| 14132 | #ifdef _WIN32 | ||
| 14133 | /* Names passed in from server are in two formats: | ||
| 14134 | 1. <database_name>/<table_name>: for normal table creation | ||
| 14135 | 2. full path: for temp table creation, or DATA DIRECTORY. | ||
| 14136 | |||
| 14137 | When srv_file_per_table is on, | ||
| 14138 | check for full path pattern, i.e. | ||
| 14139 | X:\dir\..., X is a driver letter, or | ||
| 14140 | \\dir1\dir2\..., UNC path | ||
| 14141 | returns error if it is in full path format, but not creating a temp. | ||
| 14142 | table. Currently InnoDB does not support symbolic link on Windows. */ | ||
| 14143 | |||
| 14144 | if (m_innodb_file_per_table && | ||
| 14145 | !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) { | ||
| 14146 | if (name[1] == ':' || (name[0] == '\\' && name[1] == '\\')) { | ||
| 14147 | log_errlog(ERROR_LEVEL, ER_INNODB_CANNOT_CREATE_TABLE, name); | ||
| 14148 | return HA_ERR_GENERIC; | ||
| 14149 | } | ||
| 14150 | } | ||
| 14151 | #endif /* _WIN32 */ | ||
| 14152 | |||
| 14153 |
2/4✓ Branch 0 taken 432841 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 432841 times.
|
432841 | if (!normalize_table_name(m_table_name, name)) { |
| 14154 | /* purecov: begin inspected */ | ||
| 14155 | ✗ | ut_d(ut_error); | |
| 14156 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 14157 | /* purecov: end */ | ||
| 14158 | } | ||
| 14159 | |||
| 14160 | 432841 | m_remote_path[0] = '\0'; | |
| 14161 | 432841 | m_tablespace[0] = '\0'; | |
| 14162 | |||
| 14163 | /* Set the remote path if DATA DIRECTORY is valid. If not, | ||
| 14164 | we ignore the DATA DIRECTORY. In strict mode, a non-valid | ||
| 14165 | value would have already been rejected. */ | ||
| 14166 |
2/2✓ Branch 0 taken 19206 times.
✓ Branch 1 taken 413635 times.
|
432841 | if (m_create_info->data_file_name != nullptr && |
| 14167 |
3/4✓ Branch 0 taken 475 times.
✓ Branch 1 taken 18731 times.
✓ Branch 2 taken 475 times.
✗ Branch 3 not taken.
|
19206 | *m_create_info->data_file_name != '\0' && m_table_name != nullptr) { |
| 14168 |
3/4✓ Branch 0 taken 475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 462 times.
|
475 | if (!create_option_data_directory_is_valid(true)) { |
| 14169 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
13 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED, |
| 14170 | ER_DEFAULT(WARN_OPTION_IGNORED), "DATA DIRECTORY"); | ||
| 14171 | 13 | m_flags &= ~DICT_TF_MASK_DATA_DIR; | |
| 14172 | } else { | ||
| 14173 | 462 | strncpy(m_remote_path, m_create_info->data_file_name, FN_REFLEN - 1); | |
| 14174 | } | ||
| 14175 | } | ||
| 14176 | |||
| 14177 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 432803 times.
|
432841 | if (m_create_info->index_file_name) { |
| 14178 |
2/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, WARN_OPTION_IGNORED, |
| 14179 | ER_DEFAULT(WARN_OPTION_IGNORED), "INDEX DIRECTORY"); | ||
| 14180 | } | ||
| 14181 | |||
| 14182 | /* The TABLESPACE designation has already been validated by | ||
| 14183 | create_option_tablespace_is_valid() irregardless of strict-mode. | ||
| 14184 | So it only needs to be copied now. */ | ||
| 14185 |
2/2✓ Branch 0 taken 30520 times.
✓ Branch 1 taken 402321 times.
|
432841 | if (m_use_shared_space) { |
| 14186 | 30520 | strncpy(m_tablespace, m_create_info->tablespace, NAME_LEN - 1); | |
| 14187 | } | ||
| 14188 | |||
| 14189 | 432841 | return 0; | |
| 14190 | 432841 | } | |
| 14191 | |||
| 14192 | /** Determine InnoDB table flags. | ||
| 14193 | If strict_mode=OFF, this will adjust the flags to what should be assumed. | ||
| 14194 | However, if an existing general tablespace is being targeted, we will NOT | ||
| 14195 | assume anything or adjust these flags. | ||
| 14196 | @retval true if successful, false if error */ | ||
| 14197 | 428403 | bool create_table_info_t::innobase_table_flags() { | |
| 14198 |
1/2✓ Branch 0 taken 428404 times.
✗ Branch 1 not taken.
|
428403 | DBUG_TRACE; |
| 14199 | |||
| 14200 | 428404 | const char *fts_doc_id_index_bad = nullptr; | |
| 14201 | 428404 | uint32_t zip_ssize = 0; | |
| 14202 | 428404 | const bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 14203 | 428404 | bool zip_allowed = !is_temp; | |
| 14204 | |||
| 14205 | const uint32_t zip_ssize_max = | ||
| 14206 | 428404 | std::min<uint32_t>((UNIV_PAGE_SSIZE_MAX), (PAGE_ZIP_SSIZE_MAX)); | |
| 14207 | |||
| 14208 | 428403 | m_flags = 0; | |
| 14209 | 428403 | m_flags2 = 0; | |
| 14210 | |||
| 14211 | /* Validate the page compression parameter. */ | ||
| 14212 |
1/2✓ Branch 0 taken 428404 times.
✗ Branch 1 not taken.
|
428403 | if (!create_option_compression_is_valid()) { |
| 14213 | /* No need to do anything. Warnings were issued. | ||
| 14214 | The compresion setting will be ignored later. | ||
| 14215 | If inodb_strict_mode=ON, this is called twice unless | ||
| 14216 | there was a problem before. | ||
| 14217 | If inodb_strict_mode=OFF, this is the only call. */ | ||
| 14218 | } | ||
| 14219 | |||
| 14220 | /* Validate the page encryption parameter. */ | ||
| 14221 |
2/2✓ Branch 0 taken 75202 times.
✓ Branch 1 taken 353202 times.
|
428404 | if (m_create_info->encrypt_type.length > 0) { |
| 14222 | 75202 | const char *encryption = m_create_info->encrypt_type.str; | |
| 14223 | |||
| 14224 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75202 times.
|
75202 | if (Encryption::validate(encryption) != DB_SUCCESS) { |
| 14225 | /* Incorrect encryption option */ | ||
| 14226 | ✗ | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); | |
| 14227 | ✗ | return false; | |
| 14228 | } | ||
| 14229 | } | ||
| 14230 | |||
| 14231 | /* Check if there are any FTS indexes defined on this table. */ | ||
| 14232 |
2/2✓ Branch 0 taken 196570 times.
✓ Branch 1 taken 428401 times.
|
624971 | for (uint i = 0; i < m_form->s->keys; i++) { |
| 14233 | 196570 | const KEY *key = &m_form->key_info[i]; | |
| 14234 | |||
| 14235 |
2/2✓ Branch 0 taken 2209 times.
✓ Branch 1 taken 194361 times.
|
196570 | if (key->flags & HA_FULLTEXT) { |
| 14236 | 2209 | m_flags2 |= DICT_TF2_FTS; | |
| 14237 | |||
| 14238 | /* We don't support FTS indexes in temporary | ||
| 14239 | tables. */ | ||
| 14240 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2208 times.
|
2209 | if (is_temp) { |
| 14241 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_error(ER_INNODB_NO_FT_TEMP_TABLE, MYF(0)); |
| 14242 | 1 | return false; | |
| 14243 | } | ||
| 14244 | |||
| 14245 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2206 times.
|
2208 | if (fts_doc_id_index_bad) { |
| 14246 | 2 | goto index_bad; | |
| 14247 | } | ||
| 14248 |
2/2✓ Branch 0 taken 1200 times.
✓ Branch 1 taken 193161 times.
|
194361 | } else if (key->flags & HA_SPATIAL) { |
| 14249 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1200 times.
|
1200 | assert(~m_create_info->options & |
| 14250 | (HA_LEX_CREATE_TMP_TABLE | HA_LEX_CREATE_INTERNAL_TMP_TABLE)); | ||
| 14251 | } | ||
| 14252 | |||
| 14253 |
3/4✓ Branch 0 taken 196567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 196519 times.
✓ Branch 3 taken 48 times.
|
196567 | if (innobase_strcasecmp(key->name, FTS_DOC_ID_INDEX_NAME)) { |
| 14254 | 196519 | continue; | |
| 14255 | } | ||
| 14256 | |||
| 14257 | /* Do a pre-check on FTS DOC ID index */ | ||
| 14258 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | if (!(key->flags & HA_NOSAME) |
| 14259 | /* For now, we do not allow a descending index, | ||
| 14260 | because fts_doc_fetch_by_doc_id() uses the | ||
| 14261 | InnODB SQL interpreter to look up FTS_DOC_ID.*/ | ||
| 14262 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 5 times.
|
48 | || (key->key_part[0].key_part_flag & HA_REVERSE_SORT) || |
| 14263 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | strcmp(key->name, FTS_DOC_ID_INDEX_NAME) || |
| 14264 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
|
43 | strcmp(key->key_part[0].field->field_name, FTS_DOC_ID_COL_NAME)) { |
| 14265 | 7 | fts_doc_id_index_bad = key->name; | |
| 14266 | } | ||
| 14267 | |||
| 14268 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
48 | if (fts_doc_id_index_bad && (m_flags2 & DICT_TF2_FTS)) { |
| 14269 | ✗ | index_bad: | |
| 14270 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0), fts_doc_id_index_bad); |
| 14271 | 2 | return false; | |
| 14272 | } | ||
| 14273 | } | ||
| 14274 | |||
| 14275 |
4/4✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199620 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 228765 times.
|
428401 | if (is_temp && m_create_info->key_block_size > 0) { |
| 14276 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, |
| 14277 | "InnoDB: KEY_BLOCK_SIZE is ignored" | ||
| 14278 | " for TEMPORARY TABLE."); | ||
| 14279 | 16 | zip_allowed = false; | |
| 14280 |
2/2✓ Branch 0 taken 552 times.
✓ Branch 1 taken 427833 times.
|
428385 | } else if (m_create_info->key_block_size > 0) { |
| 14281 |
1/2✓ Branch 0 taken 552 times.
✗ Branch 1 not taken.
|
552 | zip_ssize = get_zip_shift_size(m_create_info->key_block_size); |
| 14282 | |||
| 14283 | /* Make sure compressed row format is allowed. */ | ||
| 14284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 552 times.
|
552 | if (is_temp) { |
| 14285 | ✗ | push_warning(m_thd, Sql_condition::SL_WARNING, | |
| 14286 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14287 | "InnoDB: KEY_BLOCK_SIZE is ignored" | ||
| 14288 | " for TEMPORARY TABLE."); | ||
| 14289 | ✗ | zip_allowed = false; | |
| 14290 |
3/4✓ Branch 0 taken 15 times.
✓ Branch 1 taken 537 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
552 | } else if (!m_allow_file_per_table && !m_use_shared_space) { |
| 14291 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | push_warning(m_thd, Sql_condition::SL_WARNING, |
| 14292 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14293 | "InnoDB: KEY_BLOCK_SIZE requires" | ||
| 14294 | " innodb_file_per_table."); | ||
| 14295 | 15 | zip_allowed = false; | |
| 14296 | } | ||
| 14297 | |||
| 14298 |
5/6✓ Branch 0 taken 537 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 532 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
552 | if (!zip_allowed || (!zip_ssize && m_create_info->key_block_size)) { |
| 14299 | 20 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14300 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14301 | "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32 ".", | ||
| 14302 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | m_create_info->key_block_size); |
| 14303 | } | ||
| 14304 | } | ||
| 14305 | |||
| 14306 | 428401 | enum row_type row_type = m_form->s->row_type; | |
| 14307 | |||
| 14308 |
4/4✓ Branch 0 taken 546 times.
✓ Branch 1 taken 427855 times.
✓ Branch 2 taken 532 times.
✓ Branch 3 taken 14 times.
|
428401 | if (zip_ssize && zip_allowed) { |
| 14309 | /* if ROW_FORMAT is set to default, | ||
| 14310 | automatically change it to COMPRESSED. */ | ||
| 14311 |
2/2✓ Branch 0 taken 178 times.
✓ Branch 1 taken 354 times.
|
532 | if (row_type == ROW_TYPE_DEFAULT) { |
| 14312 | 178 | row_type = ROW_TYPE_COMPRESSED; | |
| 14313 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 336 times.
|
354 | } else if (row_type != ROW_TYPE_COMPRESSED) { |
| 14314 | /* ROW_FORMAT other than COMPRESSED | ||
| 14315 | ignores KEY_BLOCK_SIZE. It does not | ||
| 14316 | make sense to reject conflicting | ||
| 14317 | KEY_BLOCK_SIZE and ROW_FORMAT, because | ||
| 14318 | such combinations can be obtained | ||
| 14319 | with ALTER TABLE anyway. */ | ||
| 14320 | 18 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14321 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14322 | "InnoDB: ignoring KEY_BLOCK_SIZE=%" PRIu32 | ||
| 14323 | " as ROW_FORMAT is not COMPRESSED.", | ||
| 14324 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | m_create_info->key_block_size); |
| 14325 | 18 | zip_allowed = false; | |
| 14326 | } | ||
| 14327 | } else { | ||
| 14328 | /* zip_ssize == 0 means no KEY_BLOCK_SIZE. */ | ||
| 14329 |
4/4✓ Branch 0 taken 297 times.
✓ Branch 1 taken 427572 times.
✓ Branch 2 taken 277 times.
✓ Branch 3 taken 20 times.
|
427869 | if (row_type == ROW_TYPE_COMPRESSED && zip_allowed) { |
| 14330 | /* ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE | ||
| 14331 | implies half the maximum KEY_BLOCK_SIZE(*1k) or | ||
| 14332 | UNIV_PAGE_SIZE, whichever is less. */ | ||
| 14333 | 277 | zip_ssize = zip_ssize_max - 1; | |
| 14334 | } | ||
| 14335 | } | ||
| 14336 | |||
| 14337 |
1/2✓ Branch 0 taken 428400 times.
✗ Branch 1 not taken.
|
428401 | rec_format_t innodb_row_format = get_row_format(innodb_default_row_format); |
| 14338 |
6/7✓ Branch 0 taken 701 times.
✓ Branch 1 taken 815 times.
✓ Branch 2 taken 811 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 38066 times.
✓ Branch 5 taken 388002 times.
✗ Branch 6 not taken.
|
428400 | switch (row_type) { |
| 14339 | 701 | case ROW_TYPE_REDUNDANT: | |
| 14340 | 701 | innodb_row_format = REC_FORMAT_REDUNDANT; | |
| 14341 | 701 | break; | |
| 14342 | 815 | case ROW_TYPE_COMPACT: | |
| 14343 | 815 | innodb_row_format = REC_FORMAT_COMPACT; | |
| 14344 | 815 | break; | |
| 14345 | |||
| 14346 | 811 | case ROW_TYPE_COMPRESSED: | |
| 14347 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 798 times.
|
811 | if (is_temp) { |
| 14348 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 14349 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14350 | "InnoDB: %s is ignored for TEMPORARY TABLE.", | ||
| 14351 | get_row_format_name(row_type)); | ||
| 14352 | |||
| 14353 | /* DYNAMIC row format is closer to COMPRESSED | ||
| 14354 | in that it supports better for large BLOBs. */ | ||
| 14355 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | push_warning(m_thd, Sql_condition::SL_WARNING, |
| 14356 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14357 | "InnoDB: assuming ROW_FORMAT=DYNAMIC."); | ||
| 14358 | |||
| 14359 | 13 | row_type = ROW_TYPE_DYNAMIC; | |
| 14360 | 13 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 14361 | 13 | break; | |
| 14362 | } | ||
| 14363 | |||
| 14364 | /* ROW_FORMAT=COMPRESSED requires file_per_table unless | ||
| 14365 | there is a target tablespace. */ | ||
| 14366 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 790 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
|
798 | if (!m_allow_file_per_table && !m_use_shared_space) { |
| 14367 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | push_warning_printf(m_thd, Sql_condition::SL_WARNING, |
| 14368 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14369 | "InnoDB: %s requires innodb_file_per_table.", | ||
| 14370 | get_row_format_name(row_type)); | ||
| 14371 | } else { | ||
| 14372 | /* We can use this row_format. */ | ||
| 14373 | 790 | innodb_row_format = REC_FORMAT_COMPRESSED; | |
| 14374 | 790 | break; | |
| 14375 | } | ||
| 14376 | 8 | zip_allowed = false; | |
| 14377 | /* fall through to set row_type = DYNAMIC */ | ||
| 14378 | [[fallthrough]]; | ||
| 14379 | 13 | case ROW_TYPE_NOT_USED: | |
| 14380 | case ROW_TYPE_FIXED: | ||
| 14381 | case ROW_TYPE_PAGED: | ||
| 14382 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | push_warning(m_thd, Sql_condition::SL_WARNING, |
| 14383 | ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14384 | "InnoDB: assuming ROW_FORMAT=DYNAMIC."); | ||
| 14385 | [[fallthrough]]; | ||
| 14386 | 38079 | case ROW_TYPE_DYNAMIC: | |
| 14387 | 38079 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 14388 | 38079 | break; | |
| 14389 | 388002 | case ROW_TYPE_DEFAULT: { | |
| 14390 | /* Consider the real_row_type if already set. */ | ||
| 14391 |
4/5✓ Branch 0 taken 31 times.
✓ Branch 1 taken 143 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 387816 times.
✓ Branch 4 taken 12 times.
|
388002 | switch (m_form->s->real_row_type) { |
| 14392 | 31 | case ROW_TYPE_REDUNDANT: | |
| 14393 | 31 | innodb_row_format = REC_FORMAT_REDUNDANT; | |
| 14394 | 31 | break; | |
| 14395 | 143 | case ROW_TYPE_COMPACT: | |
| 14396 | 143 | innodb_row_format = REC_FORMAT_COMPACT; | |
| 14397 | 143 | break; | |
| 14398 | ✗ | case ROW_TYPE_COMPRESSED: | |
| 14399 | ✗ | innodb_row_format = REC_FORMAT_COMPRESSED; | |
| 14400 | ✗ | break; | |
| 14401 | 387816 | case ROW_TYPE_DYNAMIC: | |
| 14402 | 387816 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 14403 | 387816 | break; | |
| 14404 | 12 | default: | |
| 14405 | 12 | break; | |
| 14406 | } | ||
| 14407 | 388002 | break; | |
| 14408 | } | ||
| 14409 | ✗ | default: | |
| 14410 | ✗ | ut_d(ut_error); | |
| 14411 | } | ||
| 14412 | |||
| 14413 | /* Don't support compressed table when page size > 16k. */ | ||
| 14414 |
6/6✓ Branch 0 taken 199585 times.
✓ Branch 1 taken 228815 times.
✓ Branch 2 taken 790 times.
✓ Branch 3 taken 198795 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 778 times.
|
428400 | if (zip_allowed && zip_ssize && UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) { |
| 14415 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | push_warning(m_thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, |
| 14416 | "InnoDB: Cannot create a COMPRESSED table" | ||
| 14417 | " when innodb_page_size > 16k." | ||
| 14418 | " Assuming ROW_FORMAT=DYNAMIC."); | ||
| 14419 | 12 | zip_allowed = false; | |
| 14420 | } | ||
| 14421 | |||
| 14422 |
4/6✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199619 times.
✓ Branch 2 taken 228781 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 428400 times.
|
428400 | ut_ad(!is_temp || !zip_allowed); |
| 14423 |
4/6✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199619 times.
✓ Branch 2 taken 228781 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 428400 times.
|
428400 | ut_ad(!is_temp || row_type != ROW_TYPE_COMPRESSED); |
| 14424 |
5/6✓ Branch 0 taken 228780 times.
✓ Branch 1 taken 199620 times.
✓ Branch 2 taken 228780 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 428400 times.
|
428400 | ut_ad(!is_temp || innodb_row_format != REC_FORMAT_COMPRESSED); |
| 14425 | |||
| 14426 | /* Set the table flags */ | ||
| 14427 |
2/2✓ Branch 0 taken 228827 times.
✓ Branch 1 taken 199573 times.
|
428400 | if (!zip_allowed) { |
| 14428 | 228827 | zip_ssize = 0; | |
| 14429 | } | ||
| 14430 | |||
| 14431 |
2/2✓ Branch 0 taken 228781 times.
✓ Branch 1 taken 199619 times.
|
428400 | if (is_temp) { |
| 14432 | 228781 | m_flags2 |= DICT_TF2_TEMPORARY; | |
| 14433 | |||
| 14434 |
2/2✓ Branch 0 taken 182646 times.
✓ Branch 1 taken 46135 times.
|
228781 | if (m_create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE) { |
| 14435 | /* Intrinsic tables reside only in the shared temporary | ||
| 14436 | tablespace and we will always use ROW_FORMAT=DYNAMIC. */ | ||
| 14437 | /* We do not allow compressed instrinsic temporary tables. */ | ||
| 14438 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 182646 times.
|
182646 | ut_ad(zip_ssize == 0); |
| 14439 | 182646 | innodb_row_format = REC_FORMAT_DYNAMIC; | |
| 14440 | 182646 | m_flags2 |= DICT_TF2_INTRINSIC; | |
| 14441 | } | ||
| 14442 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 228772 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
228781 | if (m_use_shared_space && m_create_info->tablespace != nullptr && |
| 14443 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | strcmp(m_create_info->tablespace, dict_sys_t::s_temp_space_name) == 0) { |
| 14444 | /* This is possible only with innodb_strict_mode=OFF and we warned that | ||
| 14445 | that tablespace=innodb_temporary is ignored. We should instead use | ||
| 14446 | session temporary tablespaces */ | ||
| 14447 | 9 | m_use_shared_space = false; | |
| 14448 | } | ||
| 14449 | |||
| 14450 |
2/2✓ Branch 0 taken 150894 times.
✓ Branch 1 taken 48725 times.
|
199619 | } else if (m_use_file_per_table) { |
| 14451 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150894 times.
|
150894 | ut_ad(!m_use_shared_space); |
| 14452 | 150894 | m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE; | |
| 14453 | } | ||
| 14454 | |||
| 14455 | /* Set the table flags */ | ||
| 14456 | 428400 | dict_tf_set(&m_flags, innodb_row_format, zip_ssize, m_use_data_dir, | |
| 14457 |
1/2✓ Branch 0 taken 428400 times.
✗ Branch 1 not taken.
|
428400 | m_use_shared_space); |
| 14458 | |||
| 14459 | 428400 | return true; | |
| 14460 | 428403 | } | |
| 14461 | |||
| 14462 | /** Detach the just created table and its auxiliary tables if exist */ | ||
| 14463 | 146491 | void create_table_info_t::detach() { | |
| 14464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
|
146491 | ut_ad(!dict_sys_mutex_own()); |
| 14465 | 146491 | dict_sys_mutex_enter(); | |
| 14466 | |||
| 14467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
|
146491 | ut_ad(m_table != nullptr); |
| 14468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
|
146491 | ut_ad(!m_table->can_be_evicted); |
| 14469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 146491 times.
|
146491 | ut_ad(!m_table->is_temporary()); |
| 14470 | |||
| 14471 |
2/2✓ Branch 0 taken 134757 times.
✓ Branch 1 taken 11734 times.
|
146491 | if (!m_table->explicitly_non_lru) { |
| 14472 | 134757 | dict_table_allow_eviction(m_table); | |
| 14473 | } | ||
| 14474 | |||
| 14475 |
2/2✓ Branch 0 taken 145948 times.
✓ Branch 1 taken 543 times.
|
146491 | if ((m_table->flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) || |
| 14476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 145948 times.
|
145948 | m_table->fts != nullptr) { |
| 14477 | 543 | fts_detach_aux_tables(m_table, true); | |
| 14478 | } | ||
| 14479 | |||
| 14480 | 146491 | dict_sys_mutex_exit(); | |
| 14481 | 146491 | } | |
| 14482 | |||
| 14483 | /** Parse MERGE_THRESHOLD value from the string. | ||
| 14484 | @param[in] thd connection | ||
| 14485 | @param[in] str string which might include 'MERGE_THRESHOLD=' | ||
| 14486 | @return value parsed. 0 means not found or invalid value. */ | ||
| 14487 | 33595 | static ulint innobase_parse_merge_threshold(THD *thd, const char *str) { | |
| 14488 | static const char *label = "MERGE_THRESHOLD="; | ||
| 14489 |
3/4✓ Branch 0 taken 531 times.
✓ Branch 1 taken 33064 times.
✓ Branch 2 taken 531 times.
✗ Branch 3 not taken.
|
33595 | static const size_t label_len = strlen(label); |
| 14490 | 33595 | const char *pos = str; | |
| 14491 | |||
| 14492 | 33595 | pos = strstr(str, label); | |
| 14493 | |||
| 14494 |
2/2✓ Branch 0 taken 33528 times.
✓ Branch 1 taken 67 times.
|
33595 | if (pos == nullptr) { |
| 14495 | 33528 | return (0); | |
| 14496 | } | ||
| 14497 | |||
| 14498 | 67 | pos += label_len; | |
| 14499 | |||
| 14500 | 67 | lint ret = atoi(pos); | |
| 14501 | |||
| 14502 |
4/4✓ Branch 0 taken 58 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 10 times.
|
67 | if (ret > 0 && ret <= 50) { |
| 14503 | 48 | return (static_cast<ulint>(ret)); | |
| 14504 | } | ||
| 14505 | |||
| 14506 | 19 | push_warning_printf( | |
| 14507 | thd, Sql_condition::SL_WARNING, ER_ILLEGAL_HA_CREATE_OPTION, | ||
| 14508 | "InnoDB: Invalid value for MERGE_THRESHOLD in the CREATE TABLE" | ||
| 14509 | " statement. The value is ignored."); | ||
| 14510 | |||
| 14511 | 19 | return (0); | |
| 14512 | } | ||
| 14513 | |||
| 14514 | /** Parse hint for table and its indexes, and update the information | ||
| 14515 | in dictionary. | ||
| 14516 | @param[in] thd Connection thread | ||
| 14517 | @param[in,out] table Target table | ||
| 14518 | @param[in] table_share Table definition */ | ||
| 14519 | 473479 | void innobase_parse_hint_from_comment(THD *thd, dict_table_t *table, | |
| 14520 | const TABLE_SHARE *table_share) { | ||
| 14521 | ulint merge_threshold_table; | ||
| 14522 | ulint merge_threshold_index[MAX_KEY]; | ||
| 14523 | bool is_found[MAX_KEY]; | ||
| 14524 | |||
| 14525 |
2/2✓ Branch 0 taken 33391 times.
✓ Branch 1 taken 440088 times.
|
473479 | if (table_share->comment.str != nullptr) { |
| 14526 | merge_threshold_table = | ||
| 14527 |
1/2✓ Branch 0 taken 33391 times.
✗ Branch 1 not taken.
|
33391 | innobase_parse_merge_threshold(thd, table_share->comment.str); |
| 14528 | } else { | ||
| 14529 | 440088 | merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT; | |
| 14530 | } | ||
| 14531 | |||
| 14532 |
2/2✓ Branch 0 taken 33381 times.
✓ Branch 1 taken 440098 times.
|
473479 | if (merge_threshold_table == 0) { |
| 14533 | 33381 | merge_threshold_table = DICT_INDEX_MERGE_THRESHOLD_DEFAULT; | |
| 14534 | } | ||
| 14535 | |||
| 14536 |
2/2✓ Branch 0 taken 238182 times.
✓ Branch 1 taken 473479 times.
|
711661 | for (uint i = 0; i < table_share->keys; i++) { |
| 14537 | 238182 | KEY *key_info = &table_share->key_info[i]; | |
| 14538 | |||
| 14539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 238182 times.
|
238182 | ut_ad(i < sizeof(merge_threshold_index) / sizeof(merge_threshold_index[0])); |
| 14540 | |||
| 14541 |
3/4✓ Branch 0 taken 204 times.
✓ Branch 1 taken 237978 times.
✓ Branch 2 taken 204 times.
✗ Branch 3 not taken.
|
238182 | if (key_info->flags & HA_USES_COMMENT && key_info->comment.str != nullptr) { |
| 14542 | 204 | merge_threshold_index[i] = | |
| 14543 |
1/2✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
|
204 | innobase_parse_merge_threshold(thd, key_info->comment.str); |
| 14544 | } else { | ||
| 14545 | 237978 | merge_threshold_index[i] = merge_threshold_table; | |
| 14546 | } | ||
| 14547 | |||
| 14548 |
2/2✓ Branch 0 taken 166 times.
✓ Branch 1 taken 238016 times.
|
238182 | if (merge_threshold_index[i] == 0) { |
| 14549 | 166 | merge_threshold_index[i] = merge_threshold_table; | |
| 14550 | } | ||
| 14551 | } | ||
| 14552 | |||
| 14553 |
2/2✓ Branch 0 taken 238182 times.
✓ Branch 1 taken 473479 times.
|
711661 | for (uint i = 0; i < table_share->keys; i++) { |
| 14554 | 238182 | is_found[i] = false; | |
| 14555 | } | ||
| 14556 | |||
| 14557 | /* update in memory */ | ||
| 14558 |
6/10✓ Branch 0 taken 473479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 473479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 565545 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1039024 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 565545 times.
✓ Branch 9 taken 473479 times.
|
1039024 | for (auto index : table->indexes) { |
| 14559 |
2/2✓ Branch 0 taken 326224 times.
✓ Branch 1 taken 239321 times.
|
565545 | if (dict_index_is_auto_gen_clust(index)) { |
| 14560 | /* GEN_CLUST_INDEX should use merge_threshold_table */ | ||
| 14561 | |||
| 14562 | /* x-lock index is needed to exclude concurrent | ||
| 14563 | pessimistic tree operations */ | ||
| 14564 |
2/4✓ Branch 0 taken 326224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326224 times.
✗ Branch 3 not taken.
|
326224 | rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE); |
| 14565 | 326224 | index->merge_threshold = merge_threshold_table; | |
| 14566 |
2/4✓ Branch 0 taken 326224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326224 times.
✗ Branch 3 not taken.
|
326224 | rw_lock_x_unlock(dict_index_get_lock(index)); |
| 14567 | |||
| 14568 | 326224 | continue; | |
| 14569 | } | ||
| 14570 | |||
| 14571 |
2/2✓ Branch 0 taken 429162 times.
✓ Branch 1 taken 1146 times.
|
430308 | for (uint i = 0; i < table_share->keys; i++) { |
| 14572 |
2/2✓ Branch 0 taken 188841 times.
✓ Branch 1 taken 240321 times.
|
429162 | if (is_found[i]) { |
| 14573 | 188841 | continue; | |
| 14574 | } | ||
| 14575 | |||
| 14576 | 240321 | KEY *key_info = &table_share->key_info[i]; | |
| 14577 | |||
| 14578 |
3/4✓ Branch 0 taken 240321 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238175 times.
✓ Branch 3 taken 2146 times.
|
240321 | if (innobase_strcasecmp(index->name, key_info->name) == 0) { |
| 14579 | /* x-lock index is needed to exclude concurrent | ||
| 14580 | pessimistic tree operations */ | ||
| 14581 |
2/4✓ Branch 0 taken 238175 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238175 times.
✗ Branch 3 not taken.
|
238175 | rw_lock_x_lock(dict_index_get_lock(index), UT_LOCATION_HERE); |
| 14582 | 238175 | index->merge_threshold = merge_threshold_index[i]; | |
| 14583 |
2/4✓ Branch 0 taken 238175 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 238175 times.
✗ Branch 3 not taken.
|
238175 | rw_lock_x_unlock(dict_index_get_lock(index)); |
| 14584 | 238175 | is_found[i] = true; | |
| 14585 | |||
| 14586 | 238175 | break; | |
| 14587 | } | ||
| 14588 | } | ||
| 14589 | } | ||
| 14590 | 473479 | } | |
| 14591 | |||
| 14592 | /** Set m_use_* flags. */ | ||
| 14593 | 481074 | void create_table_info_t::set_tablespace_type( | |
| 14594 | bool table_being_altered_is_file_per_table) { | ||
| 14595 | /* Note whether this table will be created using a shared, | ||
| 14596 | general or system tablespace. */ | ||
| 14597 | 481074 | m_use_shared_space = tablespace_is_shared_space(m_create_info); | |
| 14598 | |||
| 14599 | /** Allow file_per_table for this table either because: | ||
| 14600 | 1) the setting innodb_file_per_table=on, | ||
| 14601 | 2) the table being altered is currently file_per_table | ||
| 14602 | 3) explicitly requested by tablespace=innodb_file_per_table. */ | ||
| 14603 |
1/2✓ Branch 0 taken 21479 times.
✗ Branch 1 not taken.
|
21479 | m_allow_file_per_table = m_innodb_file_per_table || |
| 14604 |
4/4✓ Branch 0 taken 21479 times.
✓ Branch 1 taken 459596 times.
✓ Branch 2 taken 147 times.
✓ Branch 3 taken 21332 times.
|
502554 | table_being_altered_is_file_per_table || |
| 14605 | 21479 | tablespace_is_file_per_table(m_create_info); | |
| 14606 | |||
| 14607 | 481075 | bool is_temp = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; | |
| 14608 | |||
| 14609 | /* Ignore the current innodb_file_per_table setting if we are | ||
| 14610 | creating a temporary table or if the | ||
| 14611 | TABLESPACE= phrase is using an existing shared tablespace. */ | ||
| 14612 | 481075 | m_use_file_per_table = | |
| 14613 |
6/6✓ Branch 0 taken 459743 times.
✓ Branch 1 taken 21332 times.
✓ Branch 2 taken 231120 times.
✓ Branch 3 taken 228623 times.
✓ Branch 4 taken 200312 times.
✓ Branch 5 taken 30808 times.
|
481075 | m_allow_file_per_table && !is_temp && !m_use_shared_space; |
| 14614 | |||
| 14615 | /* DATA DIRECTORY must have m_use_file_per_table. */ | ||
| 14616 | 1162462 | m_use_data_dir = m_use_file_per_table && | |
| 14617 |
4/4✓ Branch 0 taken 200312 times.
✓ Branch 1 taken 280763 times.
✓ Branch 2 taken 16299 times.
✓ Branch 3 taken 184013 times.
|
497374 | (m_create_info->data_file_name != nullptr) && |
| 14618 |
2/2✓ Branch 0 taken 648 times.
✓ Branch 1 taken 15651 times.
|
16299 | (m_create_info->data_file_name[0] != '\0'); |
| 14619 |
4/6✓ Branch 0 taken 47332 times.
✓ Branch 1 taken 433743 times.
✓ Branch 2 taken 47332 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 481075 times.
|
481075 | ut_ad(!(m_use_shared_space && m_use_data_dir)); |
| 14620 | 481075 | } | |
| 14621 | |||
| 14622 | /** Initialize the create_table_info_t object. | ||
| 14623 | @return error number */ | ||
| 14624 | 410863 | int create_table_info_t::initialize() { | |
| 14625 |
1/2✓ Branch 0 taken 410864 times.
✗ Branch 1 not taken.
|
410863 | DBUG_TRACE; |
| 14626 | |||
| 14627 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 410864 times.
|
410864 | ut_ad(m_thd != nullptr); |
| 14628 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 410863 times.
|
410864 | ut_ad(m_create_info != nullptr); |
| 14629 | |||
| 14630 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 410853 times.
|
410863 | if (m_form->s->fields > REC_MAX_N_USER_FIELDS) { |
| 14631 | 10 | return HA_ERR_TOO_MANY_FIELDS; | |
| 14632 | } | ||
| 14633 | |||
| 14634 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 410853 times.
|
410853 | ut_ad(m_form->s->row_type == m_create_info->row_type); |
| 14635 | |||
| 14636 | /* Check for name conflicts (with reserved name) for | ||
| 14637 | any user indices to be created. */ | ||
| 14638 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 410851 times.
|
410853 | if (innobase_index_name_is_reserved(m_thd, m_form->key_info, |
| 14639 |
1/2✓ Branch 0 taken 410853 times.
✗ Branch 1 not taken.
|
410853 | m_form->s->keys)) { |
| 14640 | 2 | return HA_ERR_WRONG_INDEX; | |
| 14641 | } | ||
| 14642 | |||
| 14643 | 410851 | m_trx->will_lock++; | |
| 14644 | |||
| 14645 | 410851 | m_table = nullptr; | |
| 14646 | |||
| 14647 | 410851 | return 0; | |
| 14648 | 410863 | } | |
| 14649 | |||
| 14650 | /** Initialize the autoinc of this table if necessary, which should | ||
| 14651 | be called before we flush logs, so autoinc counter can be persisted. */ | ||
| 14652 | 429022 | void create_table_info_t::initialize_autoinc() { | |
| 14653 | dict_table_t *innobase_table; | ||
| 14654 | |||
| 14655 |
2/2✓ Branch 0 taken 200216 times.
✓ Branch 1 taken 228806 times.
|
629238 | const bool persist = !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE) && |
| 14656 |
2/2✓ Branch 0 taken 17539 times.
✓ Branch 1 taken 182677 times.
|
200216 | m_form->found_next_number_field; |
| 14657 | |||
| 14658 |
4/4✓ Branch 0 taken 411483 times.
✓ Branch 1 taken 17539 times.
✓ Branch 2 taken 410627 times.
✓ Branch 3 taken 856 times.
|
429022 | if (!persist && m_create_info->auto_increment_value == 0) { |
| 14659 | 410627 | return; | |
| 14660 | } | ||
| 14661 | |||
| 14662 | innobase_table = | ||
| 14663 | 18395 | thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name); | |
| 14664 | |||
| 14665 |
1/2✓ Branch 0 taken 18395 times.
✗ Branch 1 not taken.
|
18395 | if (innobase_table == nullptr) { |
| 14666 | 18395 | innobase_table = dd_table_open_on_name_in_mem(m_table_name, false); | |
| 14667 | } else { | ||
| 14668 | ✗ | innobase_table->acquire(); | |
| 14669 | ✗ | ut_ad(innobase_table->is_intrinsic()); | |
| 14670 | } | ||
| 14671 | |||
| 14672 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18395 times.
|
18395 | assert(innobase_table != nullptr); |
| 14673 | |||
| 14674 |
2/2✓ Branch 0 taken 17539 times.
✓ Branch 1 taken 856 times.
|
18395 | if (persist) { |
| 14675 | 17539 | dict_table_autoinc_set_col_pos( | |
| 14676 | 17539 | innobase_table, m_form->found_next_number_field->field_index()); | |
| 14677 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17539 times.
|
17539 | ut_ad(dict_table_has_autoinc_col(innobase_table)); |
| 14678 | } | ||
| 14679 | |||
| 14680 | /* We need to copy the AUTOINC value from the old table if | ||
| 14681 | this is an ALTER|OPTIMIZE TABLE or CREATE INDEX because CREATE INDEX | ||
| 14682 | does a table copy too. If query was one of : | ||
| 14683 | |||
| 14684 | CREATE TABLE ...AUTO_INCREMENT = x; or | ||
| 14685 | ALTER TABLE...AUTO_INCREMENT = x; or | ||
| 14686 | OPTIMIZE TABLE t; or | ||
| 14687 | CREATE INDEX x on t(...); | ||
| 14688 | |||
| 14689 | Find out a table definition from the dictionary and get | ||
| 14690 | the current value of the auto increment field. Set a new | ||
| 14691 | value to the auto increment field if the value is greater | ||
| 14692 | than the maximum value in the column. */ | ||
| 14693 | |||
| 14694 | 18395 | enum_sql_command cmd = static_cast<enum_sql_command>(thd_sql_command(m_thd)); | |
| 14695 | |||
| 14696 |
2/2✓ Branch 0 taken 2107 times.
✓ Branch 1 taken 16288 times.
|
18395 | if (m_create_info->auto_increment_value > 0 && |
| 14697 |
4/4✓ Branch 0 taken 1766 times.
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 1724 times.
|
2107 | ((m_create_info->used_fields & HA_CREATE_USED_AUTO) || |
| 14698 |
4/4✓ Branch 0 taken 39 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 19 times.
|
42 | cmd == SQLCOM_ALTER_TABLE || cmd == SQLCOM_OPTIMIZE || |
| 14699 | cmd == SQLCOM_CREATE_INDEX)) { | ||
| 14700 | uint64_t auto_inc_value; | ||
| 14701 | |||
| 14702 | 2088 | auto_inc_value = m_create_info->auto_increment_value; | |
| 14703 | |||
| 14704 | 2088 | dict_table_autoinc_lock(innobase_table); | |
| 14705 | 2088 | dict_table_autoinc_initialize(innobase_table, auto_inc_value); | |
| 14706 | 2088 | dict_table_autoinc_unlock(innobase_table); | |
| 14707 | } | ||
| 14708 | |||
| 14709 | 18395 | dd_table_close(innobase_table, nullptr, nullptr, false); | |
| 14710 | } | ||
| 14711 | |||
| 14712 | /** Prepare to create a new table to an InnoDB database. | ||
| 14713 | @param[in] name Table name | ||
| 14714 | @return error number */ | ||
| 14715 | 433184 | int create_table_info_t::prepare_create_table(const char *name) { | |
| 14716 |
1/2✓ Branch 0 taken 433185 times.
✗ Branch 1 not taken.
|
433184 | DBUG_TRACE; |
| 14717 | |||
| 14718 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 433185 times.
|
433185 | ut_ad(m_thd != nullptr); |
| 14719 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 433185 times.
|
433185 | ut_ad(m_form->s->row_type == m_create_info->row_type); |
| 14720 | |||
| 14721 |
2/4✓ Branch 0 taken 433184 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 433184 times.
|
433185 | if (!normalize_table_name(m_table_name, name)) { |
| 14722 | /* purecov: begin inspected */ | ||
| 14723 | ✗ | ut_d(ut_error); | |
| 14724 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 14725 | /* purecov: end */ | ||
| 14726 | } | ||
| 14727 | |||
| 14728 |
1/2✓ Branch 0 taken 433185 times.
✗ Branch 1 not taken.
|
433184 | set_tablespace_type(false); |
| 14729 | |||
| 14730 | /* Validate the create options if innodb_strict_mode is set. | ||
| 14731 | Do not use the regular message for ER_ILLEGAL_HA_CREATE_OPTION | ||
| 14732 | because InnoDB might actually support the option, but not under | ||
| 14733 | the current conditions. The messages revealing the specific | ||
| 14734 | problems are reported inside this function. */ | ||
| 14735 |
3/4✓ Branch 0 taken 433185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 343 times.
✓ Branch 3 taken 432842 times.
|
433185 | if (create_options_are_invalid()) { |
| 14736 | 343 | return HA_WRONG_CREATE_OPTION; | |
| 14737 | } | ||
| 14738 | |||
| 14739 | /* Create the table flags and flags2 */ | ||
| 14740 |
6/6✓ Branch 0 taken 380704 times.
✓ Branch 1 taken 52138 times.
✓ Branch 2 taken 380691 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 380691 times.
✓ Branch 5 taken 52151 times.
|
432842 | if (flags() == 0 && flags2() == 0) { |
| 14741 |
3/4✓ Branch 0 taken 380691 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 380690 times.
|
380691 | if (!innobase_table_flags()) { |
| 14742 | 1 | return HA_WRONG_CREATE_OPTION; | |
| 14743 | } | ||
| 14744 | } | ||
| 14745 | |||
| 14746 |
5/8✓ Branch 0 taken 84 times.
✓ Branch 1 taken 432757 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 432841 times.
|
432841 | ut_ad(!high_level_read_only || is_intrinsic_temp_table()); |
| 14747 | |||
| 14748 |
1/2✓ Branch 0 taken 432840 times.
✗ Branch 1 not taken.
|
432841 | return parse_table_name(name); |
| 14749 | 433184 | } | |
| 14750 | |||
| 14751 | /** Check a column (name) is a base column for any stored column in the table | ||
| 14752 | @param[in] table TABLE* for the table | ||
| 14753 | @param[in] name column name to check | ||
| 14754 | @return true if this is a base column */ | ||
| 14755 | 267 | static bool innobase_is_base_s_col(const TABLE *table, const char *name) { | |
| 14756 |
2/2✓ Branch 0 taken 628 times.
✓ Branch 1 taken 257 times.
|
885 | for (uint i = 0; i < table->s->fields; ++i) { |
| 14757 | 628 | const Field *field = table->field[i]; | |
| 14758 | |||
| 14759 |
2/2✓ Branch 0 taken 616 times.
✓ Branch 1 taken 12 times.
|
628 | if (!innobase_is_s_fld(field)) { |
| 14760 | 616 | continue; | |
| 14761 | } | ||
| 14762 | |||
| 14763 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 2 times.
|
19 | for (uint j = 0; j < table->s->fields; ++j) { |
| 14764 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 5 times.
|
17 | if (bitmap_is_set(&field->gcol_info->base_columns_map, j)) { |
| 14765 | 12 | const Field *base_field = table->field[j]; | |
| 14766 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
|
12 | if (innobase_strcasecmp(base_field->field_name, name) == 0) { |
| 14767 | 10 | return (true); | |
| 14768 | } | ||
| 14769 | } | ||
| 14770 | } | ||
| 14771 | } | ||
| 14772 | |||
| 14773 | 257 | return (false); | |
| 14774 | } | ||
| 14775 | |||
| 14776 | /** Check any cascading foreign key columns are base columns | ||
| 14777 | for any stored columns in the table | ||
| 14778 | @param[in] dd_table dd::Table for the table | ||
| 14779 | @param[in] table TABLE* for the table | ||
| 14780 | @return DB_NO_FK_ON_S_BASE_COL if found or DB_SUCCESS */ | ||
| 14781 | 246837 | static dberr_t innobase_check_fk_base_col(const dd::Table *dd_table, | |
| 14782 | const TABLE *table) { | ||
| 14783 |
6/10✓ Branch 0 taken 246837 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246838 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246838 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22646 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 22646 times.
✓ Branch 9 taken 246828 times.
|
269473 | for (const dd::Foreign_key *key : dd_table->foreign_keys()) { |
| 14784 | 22646 | bool upd_cascade = false; | |
| 14785 | 22646 | bool del_cascade = false; | |
| 14786 | |||
| 14787 |
3/5✓ Branch 0 taken 22646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 22486 times.
✗ Branch 4 not taken.
|
22646 | switch (key->update_rule()) { |
| 14788 | 160 | case dd::Foreign_key::RULE_CASCADE: | |
| 14789 | case dd::Foreign_key::RULE_SET_NULL: | ||
| 14790 | 160 | upd_cascade = true; | |
| 14791 | 160 | break; | |
| 14792 | 22486 | case dd::Foreign_key::RULE_NO_ACTION: | |
| 14793 | case dd::Foreign_key::RULE_RESTRICT: | ||
| 14794 | case dd::Foreign_key::RULE_SET_DEFAULT: | ||
| 14795 | 22486 | break; | |
| 14796 | } | ||
| 14797 | |||
| 14798 |
3/5✓ Branch 0 taken 22646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
✓ Branch 3 taken 22528 times.
✗ Branch 4 not taken.
|
22646 | switch (key->delete_rule()) { |
| 14799 | 118 | case dd::Foreign_key::RULE_CASCADE: | |
| 14800 | case dd::Foreign_key::RULE_SET_NULL: | ||
| 14801 | 118 | del_cascade = true; | |
| 14802 | 118 | break; | |
| 14803 | 22528 | case dd::Foreign_key::RULE_NO_ACTION: | |
| 14804 | case dd::Foreign_key::RULE_RESTRICT: | ||
| 14805 | case dd::Foreign_key::RULE_SET_DEFAULT: | ||
| 14806 | 22528 | break; | |
| 14807 | } | ||
| 14808 | |||
| 14809 |
4/4✓ Branch 0 taken 22486 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 22389 times.
✓ Branch 3 taken 97 times.
|
22646 | if (!upd_cascade && !del_cascade) { |
| 14810 | 22389 | continue; | |
| 14811 | } | ||
| 14812 | |||
| 14813 |
6/10✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 257 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 267 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 267 times.
✓ Branch 9 taken 247 times.
|
514 | for (const dd::Foreign_key_element *key_e : key->elements()) { |
| 14814 |
3/6✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 267 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 267 times.
✗ Branch 5 not taken.
|
267 | dd::String_type col_name = key_e->column().name(); |
| 14815 | |||
| 14816 |
3/4✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 257 times.
|
267 | if (innobase_is_base_s_col(table, col_name.c_str())) { |
| 14817 | 10 | return (DB_NO_FK_ON_S_BASE_COL); | |
| 14818 | } | ||
| 14819 |
2/2✓ Branch 0 taken 257 times.
✓ Branch 1 taken 10 times.
|
267 | } |
| 14820 | } | ||
| 14821 | 246828 | return (DB_SUCCESS); | |
| 14822 | } | ||
| 14823 | |||
| 14824 | /** Create the internal innodb table. | ||
| 14825 | @param[in] dd_table dd::Table or nullptr for intrinsic table | ||
| 14826 | @param[in] old_part_table dd::Table from an old partition for partitioned | ||
| 14827 | table, NULL otherwise. | ||
| 14828 | @return 0 or error number */ | ||
| 14829 | 429483 | int create_table_info_t::create_table(const dd::Table *dd_table, | |
| 14830 | const dd::Table *old_part_table) { | ||
| 14831 | int error; | ||
| 14832 | uint primary_key_no; | ||
| 14833 | uint i; | ||
| 14834 | const char *stmt; | ||
| 14835 | size_t stmt_len; | ||
| 14836 | |||
| 14837 |
1/2✓ Branch 0 taken 429484 times.
✗ Branch 1 not taken.
|
429483 | DBUG_TRACE; |
| 14838 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 429484 times.
|
429484 | assert(m_form->s->keys <= MAX_KEY); |
| 14839 | |||
| 14840 | /* Check if dd table has hidden fts doc id index. | ||
| 14841 | Note: in case of TRUNCATE a fulltext table with | ||
| 14842 | hidden doc id index. */ | ||
| 14843 |
2/2✓ Branch 0 taken 246838 times.
✓ Branch 1 taken 182646 times.
|
429484 | if (dd_table != nullptr) { |
| 14844 |
1/2✓ Branch 0 taken 246838 times.
✗ Branch 1 not taken.
|
246838 | dberr_t err = innobase_check_fk_base_col(dd_table, m_form); |
| 14845 | |||
| 14846 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 246828 times.
|
246838 | if (err != DB_SUCCESS) { |
| 14847 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | error = convert_error_code_to_mysql(err, m_flags, nullptr); |
| 14848 | |||
| 14849 | 10 | return error; | |
| 14850 | } | ||
| 14851 | |||
| 14852 |
6/10✓ Branch 0 taken 246828 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246828 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246828 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 318273 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 318273 times.
✓ Branch 9 taken 246828 times.
|
565101 | for (auto index : dd_table->indexes()) { |
| 14853 |
2/4✓ Branch 0 taken 318273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318273 times.
✗ Branch 3 not taken.
|
318273 | if (my_strcasecmp(system_charset_info, index->name().c_str(), |
| 14854 |
4/4✓ Branch 0 taken 593 times.
✓ Branch 1 taken 317680 times.
✓ Branch 2 taken 586 times.
✓ Branch 3 taken 317687 times.
|
318866 | FTS_DOC_ID_INDEX_NAME) == 0 && |
| 14855 |
3/4✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 586 times.
✓ Branch 3 taken 7 times.
|
593 | index->is_hidden()) { |
| 14856 | 586 | m_flags2 |= DICT_TF2_FTS_ADD_DOC_ID; | |
| 14857 | } | ||
| 14858 | } | ||
| 14859 | } | ||
| 14860 | |||
| 14861 | /* Look for a primary key */ | ||
| 14862 | 429474 | primary_key_no = m_form->s->primary_key; | |
| 14863 | |||
| 14864 | /* Our function innobase_get_mysql_key_number_for_index assumes | ||
| 14865 | the primary key is always number 0, if it exists */ | ||
| 14866 |
4/6✓ Branch 0 taken 118927 times.
✓ Branch 1 taken 310547 times.
✓ Branch 2 taken 118927 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 429474 times.
|
429474 | ut_a(primary_key_no == MAX_KEY || primary_key_no == 0); |
| 14867 | |||
| 14868 |
1/2✓ Branch 0 taken 429406 times.
✗ Branch 1 not taken.
|
429474 | error = create_table_def(dd_table, old_part_table); |
| 14869 |
2/2✓ Branch 0 taken 235 times.
✓ Branch 1 taken 429171 times.
|
429406 | if (error) { |
| 14870 | 235 | return error; | |
| 14871 | } | ||
| 14872 | |||
| 14873 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 429171 times.
|
429171 | ut_ad(m_table != nullptr); |
| 14874 | |||
| 14875 | /* Create the keys */ | ||
| 14876 | |||
| 14877 |
4/4✓ Branch 0 taken 128525 times.
✓ Branch 1 taken 300646 times.
✓ Branch 2 taken 9741 times.
✓ Branch 3 taken 118784 times.
|
429171 | if (m_form->s->keys == 0 || primary_key_no == MAX_KEY) { |
| 14878 | /* Create an index which is used as the clustered index; | ||
| 14879 | order the rows by their row id which is internally generated | ||
| 14880 | by InnoDB */ | ||
| 14881 | |||
| 14882 | error = | ||
| 14883 |
1/2✓ Branch 0 taken 310387 times.
✗ Branch 1 not taken.
|
310387 | create_clustered_index_when_no_primary(m_trx, m_flags, m_table_name); |
| 14884 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 310362 times.
|
310387 | if (error) { |
| 14885 | 25 | return error; | |
| 14886 | } | ||
| 14887 | } | ||
| 14888 | |||
| 14889 |
2/2✓ Branch 0 taken 118784 times.
✓ Branch 1 taken 310362 times.
|
429146 | if (primary_key_no != MAX_KEY) { |
| 14890 | /* In InnoDB the clustered index must always be created | ||
| 14891 | first */ | ||
| 14892 |
1/2✓ Branch 0 taken 118733 times.
✗ Branch 1 not taken.
|
118784 | error = create_index(m_trx, m_form, m_flags, m_table_name, primary_key_no, |
| 14893 | dd_table); | ||
| 14894 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 118721 times.
|
118733 | if (error) { |
| 14895 | 12 | return error; | |
| 14896 | } | ||
| 14897 | } | ||
| 14898 | |||
| 14899 | /* Create the ancillary tables that are common to all FTS indexes on | ||
| 14900 | this table. */ | ||
| 14901 |
2/2✓ Branch 0 taken 593 times.
✓ Branch 1 taken 428490 times.
|
429083 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) { |
| 14902 | fts_doc_id_index_enum ret; | ||
| 14903 | |||
| 14904 | /* Check whether there already exists FTS_DOC_ID_INDEX */ | ||
| 14905 | 1186 | ret = innobase_fts_check_doc_id_index_in_def(m_form->s->keys, | |
| 14906 |
1/2✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
|
593 | m_form->key_info); |
| 14907 | |||
| 14908 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 593 times.
✗ Branch 2 not taken.
|
593 | switch (ret) { |
| 14909 | ✗ | case FTS_INCORRECT_DOC_ID_INDEX: | |
| 14910 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14911 | ER_WRONG_NAME_FOR_INDEX, | ||
| 14912 | " InnoDB: Index name %s is reserved" | ||
| 14913 | " for the unique index on" | ||
| 14914 | " FTS_DOC_ID column for FTS" | ||
| 14915 | " Document ID indexing" | ||
| 14916 | " on table %s. Please check" | ||
| 14917 | " the index definition to" | ||
| 14918 | " make sure it is of correct" | ||
| 14919 | " type\n", | ||
| 14920 | ✗ | FTS_DOC_ID_INDEX_NAME, m_table->name.m_name); | |
| 14921 | |||
| 14922 | ✗ | if (m_table->fts) { | |
| 14923 | ✗ | fts_free(m_table); | |
| 14924 | } | ||
| 14925 | |||
| 14926 | ✗ | my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), FTS_DOC_ID_INDEX_NAME); | |
| 14927 | ✗ | error = -1; | |
| 14928 | ✗ | return error; | |
| 14929 | 593 | case FTS_EXIST_DOC_ID_INDEX: | |
| 14930 | case FTS_NOT_EXIST_DOC_ID_INDEX: | ||
| 14931 | 593 | break; | |
| 14932 | } | ||
| 14933 | |||
| 14934 |
1/2✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
|
593 | dberr_t err = fts_create_common_tables(m_trx, m_table, m_table_name, |
| 14935 | (ret == FTS_EXIST_DOC_ID_INDEX)); | ||
| 14936 | |||
| 14937 |
1/2✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
|
593 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 14938 | |||
| 14939 | 593 | DICT_TF2_FLAG_UNSET(m_table, DICT_TF2_FTS_ADD_DOC_ID); | |
| 14940 | |||
| 14941 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 589 times.
|
593 | if (error) { |
| 14942 | 4 | return error; | |
| 14943 | } | ||
| 14944 | } | ||
| 14945 | |||
| 14946 |
2/2✓ Branch 0 taken 191638 times.
✓ Branch 1 taken 429022 times.
|
620660 | for (i = 0; i < m_form->s->keys; i++) { |
| 14947 |
2/2✓ Branch 0 taken 72919 times.
✓ Branch 1 taken 118719 times.
|
191638 | if (i != primary_key_no) { |
| 14948 |
1/2✓ Branch 0 taken 72869 times.
✗ Branch 1 not taken.
|
72919 | error = create_index(m_trx, m_form, m_flags, m_table_name, i, dd_table); |
| 14949 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 72862 times.
|
72869 | if (error) { |
| 14950 | 7 | return error; | |
| 14951 | } | ||
| 14952 | } | ||
| 14953 | } | ||
| 14954 | |||
| 14955 |
1/2✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
|
429022 | initialize_autoinc(); |
| 14956 | |||
| 14957 | /* Cache all the FTS indexes on this table in the FTS specific | ||
| 14958 | structure. They are used for FTS indexed column update handling. */ | ||
| 14959 |
2/2✓ Branch 0 taken 580 times.
✓ Branch 1 taken 428442 times.
|
429022 | if (m_flags2 & DICT_TF2_FTS) { |
| 14960 | 580 | fts_t *fts = m_table->fts; | |
| 14961 | |||
| 14962 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 580 times.
|
580 | ut_a(fts != nullptr); |
| 14963 | |||
| 14964 |
1/2✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
|
580 | dict_table_get_all_fts_indexes(m_table, fts->indexes); |
| 14965 | } | ||
| 14966 | |||
| 14967 |
1/2✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
|
429022 | stmt = innobase_get_stmt_unsafe(m_thd, &stmt_len); |
| 14968 | |||
| 14969 |
1/2✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
|
429022 | innodb_session_t *&priv = thd_to_innodb_session(m_trx->mysql_thd); |
| 14970 |
1/2✓ Branch 0 taken 429022 times.
✗ Branch 1 not taken.
|
429022 | dict_table_t *handler = priv->lookup_table_handler(m_table_name); |
| 14971 | |||
| 14972 |
5/8✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 246379 times.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 182643 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 429022 times.
|
429022 | ut_ad(handler == nullptr || handler->is_intrinsic()); |
| 14973 |
5/8✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 246379 times.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 182643 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 429022 times.
|
429022 | ut_ad(handler == nullptr || is_intrinsic_temp_table()); |
| 14974 | |||
| 14975 | /* There is no concept of foreign key for intrinsic tables. */ | ||
| 14976 |
4/6✓ Branch 0 taken 246379 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 246379 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 246379 times.
✗ Branch 5 not taken.
|
429022 | if (handler == nullptr && stmt != nullptr && dd_table != nullptr |
| 14977 | /* FIXME: NewDD: WL#6049 should add a new call to check if a table | ||
| 14978 | is a parent table of any FK. If the table is not child table, nor | ||
| 14979 | parent table, then it can skip the check: | ||
| 14980 | dd_table->foreign_keys().empty() && | ||
| 14981 | dd_table->referenced_keys().empty() */ | ||
| 14982 | ) { | ||
| 14983 | 246379 | dberr_t err = DB_SUCCESS; | |
| 14984 | |||
| 14985 |
1/2✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
|
246379 | dict_sys_mutex_enter(); |
| 14986 |
1/2✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
|
246379 | err = row_table_load_foreign_constraints(m_trx, m_table_name, dd_table); |
| 14987 |
1/2✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
|
246379 | dict_sys_mutex_exit(); |
| 14988 | |||
| 14989 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 246379 times.
|
246379 | switch (err) { |
| 14990 | ✗ | case DB_PARENT_NO_INDEX: | |
| 14991 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 14992 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 14993 | "Create table '%s' with foreign key constraint" | ||
| 14994 | " failed. There is no index in the referenced" | ||
| 14995 | " table where the referenced columns appear" | ||
| 14996 | " as the first columns.\n", | ||
| 14997 | m_table_name); | ||
| 14998 | ✗ | break; | |
| 14999 | |||
| 15000 | ✗ | case DB_CHILD_NO_INDEX: | |
| 15001 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 15002 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 15003 | "Create table '%s' with foreign key constraint" | ||
| 15004 | " failed. There is no index in the referencing" | ||
| 15005 | " table where referencing columns appear" | ||
| 15006 | " as the first columns.\n", | ||
| 15007 | m_table_name); | ||
| 15008 | ✗ | break; | |
| 15009 | ✗ | case DB_NO_FK_ON_S_BASE_COL: | |
| 15010 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 15011 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 15012 | "Create table '%s' with foreign key constraint" | ||
| 15013 | " failed. Cannot add foreign key constraint" | ||
| 15014 | " placed on the base column of stored" | ||
| 15015 | " column.\n", | ||
| 15016 | m_table_name); | ||
| 15017 | ✗ | break; | |
| 15018 | 246379 | default: | |
| 15019 | 246379 | break; | |
| 15020 | } | ||
| 15021 | |||
| 15022 |
1/2✓ Branch 0 taken 246379 times.
✗ Branch 1 not taken.
|
246379 | error = convert_error_code_to_mysql(err, m_flags, nullptr); |
| 15023 | |||
| 15024 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 246378 times.
|
246379 | if (error) { |
| 15025 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (handler != nullptr) { |
| 15026 | ✗ | priv->unregister_table_handler(m_table_name); | |
| 15027 | } | ||
| 15028 | 1 | return error; | |
| 15029 | } | ||
| 15030 | } | ||
| 15031 | |||
| 15032 | 429021 | return 0; | |
| 15033 | 429315 | } | |
| 15034 | |||
| 15035 | /** Update a new table in an InnoDB database. | ||
| 15036 | @return error number */ | ||
| 15037 | 429018 | int create_table_info_t::create_table_update_dict() { | |
| 15038 |
1/2✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
|
429018 | DBUG_TRACE; |
| 15039 | |||
| 15040 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 429021 times.
|
429021 | assert(m_table != nullptr); |
| 15041 | |||
| 15042 | #ifdef UNIV_DEBUG | ||
| 15043 |
3/4✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182643 times.
✓ Branch 3 taken 246378 times.
|
429021 | if (m_table->is_intrinsic()) { |
| 15044 | dict_table_t *innobase_table = | ||
| 15045 |
2/4✓ Branch 0 taken 182643 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
|
182643 | thd_to_innodb_session(m_thd)->lookup_table_handler(m_table_name); |
| 15046 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 182643 times.
|
182643 | ut_ad(m_table == innobase_table); |
| 15047 | } | ||
| 15048 | #endif /* UNIV_DEBUG */ | ||
| 15049 | |||
| 15050 | /* Temp table must be uncompressed and reside in tmp tablespace. */ | ||
| 15051 |
2/4✓ Branch 0 taken 429018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 429018 times.
|
429021 | ut_ad(!dict_table_is_compressed_temporary(m_table)); |
| 15052 |
2/2✓ Branch 0 taken 585 times.
✓ Branch 1 taken 428433 times.
|
429018 | if (m_table->fts != nullptr) { |
| 15053 |
1/2✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
|
585 | if (m_table->fts_doc_id_index == nullptr) { |
| 15054 | 1170 | m_table->fts_doc_id_index = | |
| 15055 |
1/2✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
|
585 | dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME); |
| 15056 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
|
585 | assert(m_table->fts_doc_id_index != nullptr); |
| 15057 | } else { | ||
| 15058 | ✗ | assert(m_table->fts_doc_id_index == | |
| 15059 | dict_table_get_index_on_name(m_table, FTS_DOC_ID_INDEX_NAME)); | ||
| 15060 | } | ||
| 15061 | } | ||
| 15062 | |||
| 15063 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 429018 times.
|
429018 | assert((m_table->fts == nullptr) == (m_table->fts_doc_id_index == nullptr)); |
| 15064 | |||
| 15065 |
1/2✓ Branch 0 taken 429017 times.
✗ Branch 1 not taken.
|
429018 | innobase_copy_frm_flags_from_create_info(m_table, m_create_info); |
| 15066 | |||
| 15067 |
1/2✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
|
429017 | dict_stats_update(m_table, DICT_STATS_EMPTY_TABLE); |
| 15068 | |||
| 15069 | /* Since no dict_table_close(), deinitialize it explicitly. */ | ||
| 15070 |
1/2✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
|
429021 | dict_stats_deinit(m_table); |
| 15071 | |||
| 15072 | /* Load server stopword into FTS cache */ | ||
| 15073 |
2/2✓ Branch 0 taken 580 times.
✓ Branch 1 taken 428441 times.
|
429021 | if (m_flags2 & DICT_TF2_FTS) { |
| 15074 |
2/4✓ Branch 0 taken 580 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 580 times.
|
580 | if (!innobase_fts_load_stopword(m_table, nullptr, m_thd)) { |
| 15075 | ✗ | return -1; | |
| 15076 | } | ||
| 15077 | } | ||
| 15078 | |||
| 15079 |
1/2✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
|
429021 | innobase_parse_hint_from_comment(m_thd, m_table, m_form->s); |
| 15080 | 429021 | return 0; | |
| 15081 | 429021 | } | |
| 15082 | |||
| 15083 | /** Update the global data dictionary. | ||
| 15084 | @param[in] dd_table dd::Table or dd::Partition | ||
| 15085 | @retval 0 On success | ||
| 15086 | @retval error number On failure */ | ||
| 15087 | template <typename Table> | ||
| 15088 | 858042 | int create_table_info_t::create_table_update_global_dd(Table *dd_table) { | |
| 15089 |
1/2✓ Branch 0 taken 429021 times.
✗ Branch 1 not taken.
|
858042 | DBUG_TRACE; |
| 15090 | |||
| 15091 |
4/4✓ Branch 0 taken 246378 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 46162 times.
✓ Branch 3 taken 200216 times.
|
858042 | if (dd_table == nullptr || (m_flags2 & DICT_TF2_TEMPORARY)) { |
| 15092 | /* No need to fill in metadata for all temporary tables. | ||
| 15093 | The Table object for temporary table is either NULL or | ||
| 15094 | a fake one, whose metadata would not be written back later */ | ||
| 15095 | 457610 | return 0; | |
| 15096 | } | ||
| 15097 | |||
| 15098 |
2/2✓ Branch 0 taken 17539 times.
✓ Branch 1 taken 182677 times.
|
400432 | if (m_form->found_next_number_field != nullptr) { |
| 15099 |
1/2✓ Branch 0 taken 17539 times.
✗ Branch 1 not taken.
|
35078 | dd_set_autoinc(dd_table->se_private_data(), |
| 15100 |
1/2✓ Branch 0 taken 17539 times.
✗ Branch 1 not taken.
|
35078 | m_create_info->auto_increment_value); |
| 15101 | } | ||
| 15102 | |||
| 15103 |
1/2✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
|
400432 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 15104 |
1/2✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
|
400432 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 15105 | |||
| 15106 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 200216 times.
|
400432 | ut_ad(m_table != nullptr); |
| 15107 |
2/4✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 200216 times.
|
400432 | ut_ad(!m_table->is_temporary()); |
| 15108 | |||
| 15109 |
1/2✓ Branch 0 taken 200216 times.
✗ Branch 1 not taken.
|
400432 | bool file_per_table = dict_table_is_file_per_table(m_table); |
| 15110 | 400432 | dd::Object_id dd_space_id = dd::INVALID_OBJECT_ID; | |
| 15111 | 400432 | bool is_dd_table = m_table->space == dict_sys_t::s_dict_space_id; | |
| 15112 | |||
| 15113 |
2/2✓ Branch 0 taken 29109 times.
✓ Branch 1 taken 171107 times.
|
400432 | if (is_dd_table) { |
| 15114 | 58218 | dd_space_id = dict_sys_t::s_dd_dict_space_id; | |
| 15115 |
2/2✓ Branch 0 taken 4727 times.
✓ Branch 1 taken 166380 times.
|
342214 | } else if (m_table->space == TRX_SYS_SPACE) { |
| 15116 | 9454 | dd_space_id = dict_sys_t::s_dd_sys_space_id; | |
| 15117 |
2/2✓ Branch 0 taken 165219 times.
✓ Branch 1 taken 1161 times.
|
332760 | } else if (file_per_table) { |
| 15118 |
1/2✓ Branch 0 taken 165219 times.
✗ Branch 1 not taken.
|
330438 | char *filename = fil_space_get_first_path(m_table->space); |
| 15119 | |||
| 15120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 165217 times.
|
330434 | if (dd_create_implicit_tablespace(client, m_table->space, |
| 15121 |
1/2✓ Branch 0 taken 165217 times.
✗ Branch 1 not taken.
|
330438 | m_table->name.m_name, filename, false, |
| 15122 | dd_space_id)) { | ||
| 15123 | ✗ | ut::free(filename); | |
| 15124 | ✗ | return HA_ERR_GENERIC; | |
| 15125 | } | ||
| 15126 | |||
| 15127 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 165218 times.
|
330434 | ut_ad(dd_space_id != dd::INVALID_OBJECT_ID); |
| 15128 | 330436 | ut::free(filename); | |
| 15129 | } else { | ||
| 15130 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
|
2322 | ut_ad(DICT_TF_HAS_SHARED_SPACE(m_table->flags)); |
| 15131 | |||
| 15132 |
1/2✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
|
2322 | dd_space_id = dd_get_space_id(*dd_table); |
| 15133 | |||
| 15134 | 2322 | const dd::Tablespace *index_space = nullptr; | |
| 15135 |
2/4✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1161 times.
|
2322 | if (client->acquire<dd::Tablespace>(dd_space_id, &index_space)) { |
| 15136 | ✗ | return HA_ERR_GENERIC; | |
| 15137 | } | ||
| 15138 | |||
| 15139 |
2/4✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1161 times.
|
2322 | DBUG_EXECUTE_IF("create_table_update_dd_fail", index_space = nullptr;); |
| 15140 | |||
| 15141 | uint32_t id; | ||
| 15142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
|
2322 | if (index_space == nullptr) { |
| 15143 | ✗ | my_error(ER_TABLESPACE_MISSING, MYF(0), m_table->name.m_name); | |
| 15144 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 15145 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2322 | } else if (index_space->se_private_data().get( |
| 15146 |
5/10✓ Branch 0 taken 1161 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1161 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1161 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1161 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1161 times.
✗ Branch 9 not taken.
|
4644 | dd_space_key_strings[DD_SPACE_ID], &id) || |
| 15147 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1161 times.
|
2322 | id != m_table->space) { |
| 15148 | ✗ | ut_ad(!"missing or incorrect tablespace id"); | |
| 15149 | ✗ | return HA_ERR_GENERIC; | |
| 15150 | } | ||
| 15151 | } | ||
| 15152 | |||
| 15153 | 400432 | m_table->dd_space_id = dd_space_id; | |
| 15154 | |||
| 15155 |
1/2✓ Branch 0 taken 200215 times.
✗ Branch 1 not taken.
|
400432 | dd_set_table_options(dd_table, m_table); |
| 15156 | |||
| 15157 |
1/2✓ Branch 0 taken 200215 times.
✗ Branch 1 not taken.
|
400430 | dd_write_table(dd_space_id, dd_table, m_table); |
| 15158 | |||
| 15159 |
2/2✓ Branch 0 taken 585 times.
✓ Branch 1 taken 199630 times.
|
400430 | if (m_flags2 & (DICT_TF2_FTS | DICT_TF2_FTS_ADD_DOC_ID)) { |
| 15160 |
1/2✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
|
1170 | ut_d(bool ret =) fts_create_common_dd_tables(m_table); |
| 15161 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 585 times.
|
1170 | ut_ad(ret); |
| 15162 |
1/2✓ Branch 0 taken 585 times.
✗ Branch 1 not taken.
|
1170 | fts_create_index_dd_tables(m_table); |
| 15163 | } | ||
| 15164 | |||
| 15165 |
2/4✓ Branch 0 taken 200214 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 200216 times.
|
400430 | ut_ad(dd_table_match(m_table, dd_table)); |
| 15166 | |||
| 15167 | 400432 | return 0; | |
| 15168 | 858042 | } | |
| 15169 | |||
| 15170 | template int create_table_info_t::create_table_update_global_dd<dd::Table>( | ||
| 15171 | dd::Table *); | ||
| 15172 | |||
| 15173 | template int create_table_info_t::create_table_update_global_dd<dd::Partition>( | ||
| 15174 | dd::Partition *); | ||
| 15175 | |||
| 15176 | template <typename Table> | ||
| 15177 | 815014 | int innobase_basic_ddl::create_impl(THD *thd, const char *name, TABLE *form, | |
| 15178 | HA_CREATE_INFO *create_info, Table *dd_tab, | ||
| 15179 | bool file_per_table, bool evictable, | ||
| 15180 | bool skip_strict, uint32_t old_flags, | ||
| 15181 | uint32_t old_flags2, | ||
| 15182 | const dd::Table *old_part_table) { | ||
| 15183 | 815014 | char norm_name[FN_REFLEN] = {'\0'}; /* {database}/{tablename} */ | |
| 15184 | 815014 | char remote_path[FN_REFLEN] = {'\0'}; /* Absolute path of table */ | |
| 15185 | 815014 | char tablespace[NAME_LEN] = {'\0'}; /* Tablespace name identifier */ | |
| 15186 | trx_t *trx; | ||
| 15187 | |||
| 15188 |
2/2✓ Branch 0 taken 89 times.
✓ Branch 1 taken 407418 times.
|
815014 | if (high_level_read_only && |
| 15189 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 84 times.
|
178 | !(create_info->options & HA_LEX_CREATE_INTERNAL_TMP_TABLE)) { |
| 15190 | 10 | return HA_ERR_INNODB_READ_ONLY; | |
| 15191 | } | ||
| 15192 | |||
| 15193 | /* Get the transaction associated with the current thd, or create one | ||
| 15194 | if not yet created */ | ||
| 15195 |
1/2✓ Branch 0 taken 407503 times.
✗ Branch 1 not taken.
|
815004 | trx = check_trx_exists(thd); |
| 15196 | |||
| 15197 |
2/2✓ Branch 0 taken 178595 times.
✓ Branch 1 taken 228908 times.
|
815006 | if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { |
| 15198 |
1/2✓ Branch 0 taken 178594 times.
✗ Branch 1 not taken.
|
357190 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 15199 | } | ||
| 15200 | |||
| 15201 |
1/2✓ Branch 0 taken 407502 times.
✗ Branch 1 not taken.
|
815004 | create_table_info_t info(thd, form, create_info, norm_name, remote_path, |
| 15202 | tablespace, file_per_table, skip_strict, old_flags, | ||
| 15203 | old_flags2, false); | ||
| 15204 | |||
| 15205 | /* Initialize the object. */ | ||
| 15206 |
1/2✓ Branch 0 taken 407503 times.
✗ Branch 1 not taken.
|
815004 | int error = info.initialize(); |
| 15207 | |||
| 15208 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 407493 times.
|
815006 | if (error != 0) { |
| 15209 | 20 | return (error); | |
| 15210 | } | ||
| 15211 | |||
| 15212 | /* Prepare for create and validate options. */ | ||
| 15213 |
1/2✓ Branch 0 taken 407492 times.
✗ Branch 1 not taken.
|
814986 | error = info.prepare_create_table(name); |
| 15214 | |||
| 15215 |
2/2✓ Branch 0 taken 332 times.
✓ Branch 1 taken 407160 times.
|
814984 | if (error != 0) { |
| 15216 | 664 | return (error); | |
| 15217 | } | ||
| 15218 | |||
| 15219 |
5/7✓ Branch 0 taken 224514 times.
✓ Branch 1 taken 182646 times.
✓ Branch 2 taken 3753 times.
✓ Branch 3 taken 403368 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3678 times.
✗ Branch 6 not taken.
|
814320 | error = info.create_table(dd_tab != nullptr ? &dd_tab->table() : nullptr, |
| 15220 | old_part_table); | ||
| 15221 |
2/2✓ Branch 0 taken 294 times.
✓ Branch 1 taken 406752 times.
|
814092 | if (error) { |
| 15222 | 588 | goto cleanup; | |
| 15223 | } | ||
| 15224 | |||
| 15225 |
1/2✓ Branch 0 taken 406749 times.
✗ Branch 1 not taken.
|
813504 | error = info.create_table_update_global_dd(dd_tab); |
| 15226 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 406749 times.
|
813498 | if (error) { |
| 15227 | ✗ | goto cleanup; | |
| 15228 | } | ||
| 15229 | |||
| 15230 |
1/2✓ Branch 0 taken 406752 times.
✗ Branch 1 not taken.
|
813498 | error = info.create_table_update_dict(); |
| 15231 | |||
| 15232 |
9/10✓ Branch 0 taken 352984 times.
✓ Branch 1 taken 53768 times.
✓ Branch 2 taken 306865 times.
✓ Branch 3 taken 46119 times.
✓ Branch 4 taken 306865 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 124222 times.
✓ Branch 7 taken 182643 times.
✓ Branch 8 taken 124222 times.
✓ Branch 9 taken 282530 times.
|
813504 | if (evictable && !(info.is_temp_table() || info.is_intrinsic_temp_table())) { |
| 15233 |
1/2✓ Branch 0 taken 124222 times.
✗ Branch 1 not taken.
|
248444 | info.detach(); |
| 15234 | } | ||
| 15235 | |||
| 15236 | 813504 | return (error); | |
| 15237 | |||
| 15238 | 588 | cleanup: | |
| 15239 |
7/8✓ Branch 0 taken 294 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 291 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 287 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 290 times.
|
588 | if (!info.is_intrinsic_temp_table() && info.is_temp_table()) { |
| 15240 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | dict_sys_mutex_enter(); |
| 15241 | |||
| 15242 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | dict_table_t *table = dict_table_check_if_in_cache_low(norm_name); |
| 15243 | |||
| 15244 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
8 | if (table != nullptr) { |
| 15245 |
3/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
8 | for (dict_index_t *index = table->first_index(); index != nullptr; |
| 15246 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | index = index->next()) { |
| 15247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
4 | ut_ad(index->space == table->space); |
| 15248 | 4 | page_no_t root = index->page; | |
| 15249 | 4 | index->page = FIL_NULL; | |
| 15250 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | dict_drop_temporary_table_index(index, root); |
| 15251 | } | ||
| 15252 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | dict_table_remove_from_cache(table); |
| 15253 | } | ||
| 15254 | |||
| 15255 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
8 | dict_sys_mutex_exit(); |
| 15256 | } else { | ||
| 15257 | dict_table_t *intrinsic_table = | ||
| 15258 |
2/4✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 290 times.
✗ Branch 3 not taken.
|
580 | thd_to_innodb_session(thd)->lookup_table_handler(info.table_name()); |
| 15259 | |||
| 15260 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 289 times.
|
580 | if (intrinsic_table != nullptr) { |
| 15261 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | thd_to_innodb_session(thd)->unregister_table_handler(info.table_name()); |
| 15262 | |||
| 15263 | ✗ | for (;;) { | |
| 15264 | dict_index_t *index; | ||
| 15265 | 2 | index = UT_LIST_GET_FIRST(intrinsic_table->indexes); | |
| 15266 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | if (index == nullptr) { |
| 15267 | 2 | break; | |
| 15268 | } | ||
| 15269 | ✗ | rw_lock_free(&index->lock); | |
| 15270 | ✗ | UT_LIST_REMOVE(intrinsic_table->indexes, index); | |
| 15271 | ✗ | dict_mem_index_free(index); | |
| 15272 | ✗ | index = nullptr; | |
| 15273 | } | ||
| 15274 | |||
| 15275 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | dict_mem_table_free(intrinsic_table); |
| 15276 | 2 | intrinsic_table = nullptr; | |
| 15277 | } | ||
| 15278 | } | ||
| 15279 | |||
| 15280 | 588 | return (error); | |
| 15281 | } | ||
| 15282 | |||
| 15283 | template int innobase_basic_ddl::create_impl<dd::Table>( | ||
| 15284 | THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Table *, bool, bool, | ||
| 15285 | bool, uint32_t, uint32_t, const dd::Table *); | ||
| 15286 | |||
| 15287 | template int innobase_basic_ddl::create_impl<dd::Partition>( | ||
| 15288 | THD *, const char *, TABLE *, HA_CREATE_INFO *, dd::Partition *, bool, bool, | ||
| 15289 | bool, uint32_t, uint32_t, const dd::Table *); | ||
| 15290 | |||
| 15291 | template <typename Table> | ||
| 15292 | 808344 | int innobase_basic_ddl::delete_impl(THD *thd, const char *name, | |
| 15293 | const Table *dd_tab, const TABLE *td) { | ||
| 15294 | 808344 | dberr_t error = DB_SUCCESS; | |
| 15295 | char norm_name[FN_REFLEN]; | ||
| 15296 | |||
| 15297 |
2/6✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 404172 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
808344 | DBUG_EXECUTE_IF("test_normalize_table_name", test_normalize_table_name();); |
| 15298 |
2/6✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 404172 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
808344 | DBUG_EXECUTE_IF("test_ut_format_name", test_ut_format_name();); |
| 15299 | |||
| 15300 | /* Strangely, MySQL passes the table name without the '.frm' | ||
| 15301 | extension, in contrast to ::create */ | ||
| 15302 |
2/4✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 404172 times.
|
808344 | if (!normalize_table_name(norm_name, name)) { |
| 15303 | /* purecov: begin inspected */ | ||
| 15304 | ✗ | ut_d(ut_error); | |
| 15305 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 15306 | /* purecov: end */ | ||
| 15307 | } | ||
| 15308 | |||
| 15309 |
1/2✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
|
808344 | innodb_session_t *&priv = thd_to_innodb_session(thd); |
| 15310 |
1/2✓ Branch 0 taken 404172 times.
✗ Branch 1 not taken.
|
808344 | dict_table_t *handler = priv->lookup_table_handler(norm_name); |
| 15311 | |||
| 15312 |
2/2✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 221529 times.
|
808344 | if (handler != nullptr) { |
| 15313 |
6/10✓ Branch 0 taken 182643 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 185015 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 367658 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 185015 times.
✓ Branch 9 taken 182643 times.
|
1100602 | for (auto index : handler->indexes) { |
| 15314 |
2/2✓ Branch 0 taken 113391 times.
✓ Branch 1 taken 71624 times.
|
370030 | if (index->last_ins_cur) { |
| 15315 | /* last_ins_cur and last_sel_cur are allocated together, therefore only | ||
| 15316 | checking last_ins_cur before releasing mtr */ | ||
| 15317 |
1/2✓ Branch 0 taken 113391 times.
✗ Branch 1 not taken.
|
226782 | index->last_ins_cur->release(); |
| 15318 |
1/2✓ Branch 0 taken 113391 times.
✗ Branch 1 not taken.
|
226782 | index->last_sel_cur->release(); |
| 15319 | } | ||
| 15320 | } | ||
| 15321 |
2/2✓ Branch 0 taken 221525 times.
✓ Branch 1 taken 4 times.
|
443058 | } else if (srv_read_only_mode || |
| 15322 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 221523 times.
|
443050 | srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) { |
| 15323 | 12 | return (HA_ERR_TABLE_READONLY); | |
| 15324 | } | ||
| 15325 | |||
| 15326 |
1/2✓ Branch 0 taken 404166 times.
✗ Branch 1 not taken.
|
808332 | trx_t *trx = check_trx_exists(thd); |
| 15327 | |||
| 15328 |
1/2✓ Branch 0 taken 404166 times.
✗ Branch 1 not taken.
|
808332 | TrxInInnoDB trx_in_innodb(trx); |
| 15329 | |||
| 15330 | 808332 | ulint name_len = strlen(name); | |
| 15331 | |||
| 15332 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 404166 times.
|
808332 | ut_a(name_len < 1000); |
| 15333 | |||
| 15334 | /* Either the transaction is already flagged as a locking transaction | ||
| 15335 | or it hasn't been started yet. */ | ||
| 15336 | |||
| 15337 |
5/8✓ Branch 0 taken 404166 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169712 times.
✓ Branch 3 taken 234454 times.
✓ Branch 4 taken 169712 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 404166 times.
|
808332 | ut_a(!trx_is_started(trx) || trx->will_lock > 0); |
| 15338 | |||
| 15339 | /* We are doing a DDL operation. */ | ||
| 15340 | 808332 | ++trx->will_lock; | |
| 15341 | |||
| 15342 | 808332 | bool file_per_table = false; | |
| 15343 |
7/8✓ Branch 0 taken 221523 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 221523 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 175375 times.
✓ Branch 5 taken 46148 times.
✓ Branch 6 taken 175375 times.
✓ Branch 7 taken 228791 times.
|
808332 | if (dd_tab != nullptr && dd_tab->is_persistent()) { |
| 15344 | dict_table_t *tab; | ||
| 15345 | |||
| 15346 |
1/2✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
|
350750 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 15347 |
1/2✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
|
350750 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 15348 | |||
| 15349 |
2/3✓ Branch 0 taken 25934 times.
✓ Branch 1 taken 149441 times.
✗ Branch 2 not taken.
|
402618 | int err = dd_table_open_on_dd_obj( |
| 15350 |
1/2✓ Branch 0 taken 25934 times.
✗ Branch 1 not taken.
|
51868 | thd, client, dd_tab->table(), |
| 15351 |
5/7✓ Branch 0 taken 25934 times.
✓ Branch 1 taken 149441 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25934 times.
✓ Branch 4 taken 149441 times.
✓ Branch 5 taken 25934 times.
✗ Branch 6 not taken.
|
350750 | (!dd_table_is_partitioned(dd_tab->table()) |
| 15352 | ? nullptr | ||
| 15353 | : reinterpret_cast<const dd::Partition *>(dd_tab)), | ||
| 15354 | norm_name, tab, td); | ||
| 15355 | |||
| 15356 |
2/4✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 175375 times.
✗ Branch 3 not taken.
|
350750 | if (err == 0 && tab != nullptr) { |
| 15357 |
10/11✓ Branch 0 taken 111759 times.
✓ Branch 1 taken 63616 times.
✓ Branch 2 taken 17120 times.
✓ Branch 3 taken 94639 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17120 times.
✓ Branch 6 taken 94639 times.
✓ Branch 7 taken 17120 times.
✓ Branch 8 taken 149441 times.
✓ Branch 9 taken 17120 times.
✓ Branch 10 taken 8814 times.
|
350750 | if (tab->can_be_evicted && dd_table_is_partitioned(dd_tab->table())) { |
| 15358 |
1/2✓ Branch 0 taken 17120 times.
✗ Branch 1 not taken.
|
34240 | dict_sys_mutex_enter(); |
| 15359 |
1/2✓ Branch 0 taken 17120 times.
✗ Branch 1 not taken.
|
34240 | dict_table_ddl_acquire(tab); |
| 15360 |
1/2✓ Branch 0 taken 17120 times.
✗ Branch 1 not taken.
|
34240 | dict_sys_mutex_exit(); |
| 15361 | } | ||
| 15362 | |||
| 15363 |
1/2✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
|
350750 | file_per_table = dict_table_is_file_per_table(tab); |
| 15364 |
1/2✓ Branch 0 taken 175375 times.
✗ Branch 1 not taken.
|
350750 | dd_table_close(tab, thd, nullptr, false); |
| 15365 | } | ||
| 15366 | 350750 | } | |
| 15367 | |||
| 15368 |
1/2✓ Branch 0 taken 404128 times.
✗ Branch 1 not taken.
|
808332 | error = row_drop_table_for_mysql(norm_name, trx, true, handler); |
| 15369 | |||
| 15370 |
3/4✓ Branch 0 taken 182643 times.
✓ Branch 1 taken 221485 times.
✓ Branch 2 taken 182643 times.
✗ Branch 3 not taken.
|
808256 | if (handler != nullptr && error == DB_SUCCESS) { |
| 15371 |
1/2✓ Branch 0 taken 182643 times.
✗ Branch 1 not taken.
|
365286 | priv->unregister_table_handler(norm_name); |
| 15372 | } | ||
| 15373 | |||
| 15374 |
4/4✓ Branch 0 taken 404126 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 164322 times.
✓ Branch 3 taken 239804 times.
|
808256 | if (error == DB_SUCCESS && file_per_table) { |
| 15375 |
2/4✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 164322 times.
✗ Branch 3 not taken.
|
328644 | dd::Object_id dd_space_id = dd_first_index(dd_tab)->tablespace_id(); |
| 15376 |
1/2✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
|
328644 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 15377 |
1/2✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
|
328644 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 15378 | |||
| 15379 |
3/4✓ Branch 0 taken 164322 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 164320 times.
|
328644 | if (dd_drop_tablespace(client, dd_space_id)) { |
| 15380 | 4 | error = DB_ERROR; | |
| 15381 | } | ||
| 15382 | 328644 | } | |
| 15383 | |||
| 15384 |
1/2✓ Branch 0 taken 404128 times.
✗ Branch 1 not taken.
|
808256 | return (convert_error_code_to_mysql(error, 0, nullptr)); |
| 15385 | 808256 | } | |
| 15386 | |||
| 15387 | template int innobase_basic_ddl::delete_impl<dd::Table>(THD *, const char *, | ||
| 15388 | const dd::Table *, | ||
| 15389 | const TABLE *); | ||
| 15390 | |||
| 15391 | template int innobase_basic_ddl::delete_impl<dd::Partition>( | ||
| 15392 | THD *, const char *, const dd::Partition *, const TABLE *); | ||
| 15393 | |||
| 15394 | template <typename Table> | ||
| 15395 | 43630 | int innobase_basic_ddl::rename_impl(THD *thd, const char *from, const char *to, | |
| 15396 | const Table *from_table, | ||
| 15397 | const Table *to_table, const TABLE *td) { | ||
| 15398 | dberr_t error; | ||
| 15399 | char norm_to[FN_REFLEN]; | ||
| 15400 | char norm_from[FN_REFLEN]; | ||
| 15401 | 43630 | bool rename_file = false; | |
| 15402 | 43630 | space_id_t space = SPACE_UNKNOWN; | |
| 15403 | 43630 | dict_table_t *table = nullptr; | |
| 15404 | |||
| 15405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21815 times.
|
43630 | ut_ad(!srv_read_only_mode); |
| 15406 | |||
| 15407 |
3/6✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21815 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21815 times.
|
87260 | if (!normalize_table_name(norm_to, to) || |
| 15408 |
2/4✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21815 times.
|
43630 | !normalize_table_name(norm_from, from)) { |
| 15409 | /* purecov: begin inspected */ | ||
| 15410 | ✗ | ut_d(ut_error); | |
| 15411 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 15412 | /* purecov: end */ | ||
| 15413 | } | ||
| 15414 | |||
| 15415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21815 times.
|
43630 | ut_ad(strcmp(norm_from, norm_to) != 0); |
| 15416 | |||
| 15417 |
3/4✓ Branch 0 taken 21557 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 21557 times.
✗ Branch 3 not taken.
|
43630 | DEBUG_SYNC_C("innodb_rename_table_ready"); |
| 15418 | |||
| 15419 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | trx_t *trx = check_trx_exists(thd); |
| 15420 | |||
| 15421 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 15422 | |||
| 15423 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | TrxInInnoDB trx_in_innodb(trx); |
| 15424 | |||
| 15425 | 43630 | ++trx->will_lock; | |
| 15426 | |||
| 15427 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | dd::cache::Dictionary_client *client = dd::get_dd_client(thd); |
| 15428 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 15429 | |||
| 15430 |
2/3✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14774 times.
✗ Branch 2 not taken.
|
57712 | int err = dd_table_open_on_dd_obj( |
| 15431 |
1/2✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
|
14082 | thd, client, from_table->table(), |
| 15432 |
5/7✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14774 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7041 times.
✓ Branch 4 taken 14774 times.
✓ Branch 5 taken 7041 times.
✗ Branch 6 not taken.
|
43630 | (!dd_table_is_partitioned(from_table->table()) |
| 15433 | ? nullptr | ||
| 15434 | : reinterpret_cast<const dd::Partition *>(from_table)), | ||
| 15435 | norm_from, table, td); | ||
| 15436 |
2/4✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21815 times.
|
43630 | if (err != 0 || table == nullptr) { |
| 15437 | ✗ | error = DB_TABLE_NOT_FOUND; | |
| 15438 | ✗ | return (convert_error_code_to_mysql(error, 0, nullptr)); | |
| 15439 | } | ||
| 15440 | |||
| 15441 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | rename_file = dict_table_is_file_per_table(table); |
| 15442 | 43630 | space = table->space; | |
| 15443 | |||
| 15444 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | if (row_is_mysql_tmp_table_name(norm_from) && |
| 15445 |
6/8✓ Branch 0 taken 8487 times.
✓ Branch 1 taken 13328 times.
✓ Branch 2 taken 8487 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8487 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6578 times.
✓ Branch 7 taken 15237 times.
|
60604 | !row_is_mysql_tmp_table_name(norm_to) && |
| 15446 |
4/7✓ Branch 0 taken 1909 times.
✓ Branch 1 taken 6578 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8487 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1909 times.
|
16974 | !dd_table_is_partitioned(from_table->table())) { |
| 15447 | 13156 | table->refresh_fk = true; | |
| 15448 | } | ||
| 15449 | |||
| 15450 |
5/7✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14774 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7041 times.
✓ Branch 4 taken 14774 times.
✓ Branch 5 taken 7041 times.
✗ Branch 6 not taken.
|
43630 | if (dd_table_is_partitioned(from_table->table())) { |
| 15451 |
1/2✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
|
14082 | dict_sys_mutex_enter(); |
| 15452 |
1/2✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
|
14082 | dict_table_ddl_acquire(table); |
| 15453 |
1/2✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
|
14082 | dict_sys_mutex_exit(); |
| 15454 | } | ||
| 15455 | |||
| 15456 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | dd_table_close(table, thd, nullptr, false); |
| 15457 | |||
| 15458 | /* Serialize data dictionary operations with dictionary mutex: | ||
| 15459 | no deadlocks can occur then in these operations. */ | ||
| 15460 | |||
| 15461 |
1/2✓ Branch 0 taken 21815 times.
✗ Branch 1 not taken.
|
43630 | row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE); |
| 15462 | |||
| 15463 |
3/5✓ Branch 0 taken 7041 times.
✓ Branch 1 taken 14723 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6985 times.
✗ Branch 4 not taken.
|
43630 | error = row_rename_table_for_mysql(norm_from, norm_to, &to_table->table(), |
| 15464 | trx, false); | ||
| 15465 | |||
| 15466 |
1/2✓ Branch 0 taken 21708 times.
✗ Branch 1 not taken.
|
43416 | row_mysql_unlock_data_dictionary(trx); |
| 15467 | |||
| 15468 |
4/4✓ Branch 0 taken 21691 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 15701 times.
✓ Branch 3 taken 5990 times.
|
43416 | if (error == DB_SUCCESS && rename_file) { |
| 15469 |
1/2✓ Branch 0 taken 15701 times.
✗ Branch 1 not taken.
|
31402 | char *new_path = fil_space_get_first_path(space); |
| 15470 | |||
| 15471 |
2/4✓ Branch 0 taken 15701 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15701 times.
✗ Branch 3 not taken.
|
31402 | auto dd_space_id = dd_first_index(to_table)->tablespace_id(); |
| 15472 | |||
| 15473 |
1/2✓ Branch 0 taken 15701 times.
✗ Branch 1 not taken.
|
31402 | error = dd_tablespace_rename(dd_space_id, false, norm_to, new_path); |
| 15474 | |||
| 15475 |
2/2✓ Branch 0 taken 15685 times.
✓ Branch 1 taken 16 times.
|
31402 | if (new_path != nullptr) { |
| 15476 | 31370 | ut::free(new_path); | |
| 15477 | } | ||
| 15478 | } | ||
| 15479 | |||
| 15480 |
3/4✓ Branch 0 taken 21450 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 21450 times.
✗ Branch 3 not taken.
|
43416 | DEBUG_SYNC(thd, "after_innobase_rename_table"); |
| 15481 | |||
| 15482 |
2/2✓ Branch 0 taken 21691 times.
✓ Branch 1 taken 17 times.
|
43416 | if (error == DB_SUCCESS) { |
| 15483 | char errstr[512]; | ||
| 15484 | dberr_t ret; | ||
| 15485 | |||
| 15486 |
1/2✓ Branch 0 taken 21691 times.
✗ Branch 1 not taken.
|
43382 | ret = dict_stats_rename_table(norm_from, norm_to, errstr, sizeof(errstr)); |
| 15487 | |||
| 15488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21691 times.
|
43382 | if (ret != DB_SUCCESS) { |
| 15489 | ✗ | ib::error(ER_IB_MSG_566) << errstr; | |
| 15490 | |||
| 15491 | ✗ | push_warning(thd, Sql_condition::SL_WARNING, ER_LOCK_WAIT_TIMEOUT, | |
| 15492 | errstr); | ||
| 15493 | } | ||
| 15494 | } | ||
| 15495 | |||
| 15496 | /* The duplicate key scenario was possible only for old DD since InnoDB | ||
| 15497 | would update it internally. With new DD, the rename conflict should be | ||
| 15498 | checked by server before diving into SE */ | ||
| 15499 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21708 times.
|
43416 | ut_ad(error != DB_DUPLICATE_KEY); |
| 15500 | |||
| 15501 |
1/2✓ Branch 0 taken 21708 times.
✗ Branch 1 not taken.
|
43416 | return (convert_error_code_to_mysql(error, 0, nullptr)); |
| 15502 | 43416 | } | |
| 15503 | |||
| 15504 | template int innobase_basic_ddl::rename_impl<dd::Table>(THD *, const char *, | ||
| 15505 | const char *, | ||
| 15506 | const dd::Table *, | ||
| 15507 | const dd::Table *, | ||
| 15508 | const TABLE *); | ||
| 15509 | |||
| 15510 | template int innobase_basic_ddl::rename_impl<dd::Partition>( | ||
| 15511 | THD *, const char *, const char *, const dd::Partition *, | ||
| 15512 | const dd::Partition *, const TABLE *); | ||
| 15513 | |||
| 15514 | template <typename Table> | ||
| 15515 | 105214 | innobase_truncate<Table>::~innobase_truncate() { | |
| 15516 |
2/2✓ Branch 0 taken 52605 times.
✓ Branch 1 taken 2 times.
|
105214 | if (m_table != nullptr) { |
| 15517 | 105210 | dd_table_close(m_table, m_thd, nullptr, false); | |
| 15518 | 105210 | m_table = nullptr; | |
| 15519 | } | ||
| 15520 | 105214 | } | |
| 15521 | |||
| 15522 | template innobase_truncate<dd::Table>::~innobase_truncate(); | ||
| 15523 | template innobase_truncate<dd::Partition>::~innobase_truncate(); | ||
| 15524 | |||
| 15525 | template <typename Table> | ||
| 15526 | 105246 | int innobase_truncate<Table>::open_table(dict_table_t *&innodb_table) { | |
| 15527 |
2/2✓ Branch 0 taken 52580 times.
✓ Branch 1 taken 43 times.
|
105246 | if (m_dd_table->table().is_persistent()) { |
| 15528 |
1/2✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
|
105160 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 15529 |
1/2✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
|
105160 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 15530 | |||
| 15531 |
1/2✓ Branch 0 taken 50068 times.
✗ Branch 1 not taken.
|
205296 | int error = dd_table_open_on_dd_obj( |
| 15532 |
2/4✓ Branch 0 taken 2512 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2512 times.
✗ Branch 3 not taken.
|
105160 | m_thd, client, m_dd_table->table(), |
| 15533 |
3/4✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2512 times.
✓ Branch 3 taken 50068 times.
|
105160 | (dd_table_is_partitioned(m_dd_table->table()) |
| 15534 | ? reinterpret_cast<const dd::Partition *>(m_dd_table) | ||
| 15535 | : nullptr), | ||
| 15536 |
1/2✓ Branch 0 taken 2512 times.
✗ Branch 1 not taken.
|
105160 | m_name, innodb_table, m_form); |
| 15537 | |||
| 15538 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52580 times.
|
105160 | if (error != 0) { |
| 15539 | ✗ | return (error); | |
| 15540 | } | ||
| 15541 |
1/2✓ Branch 0 taken 52580 times.
✗ Branch 1 not taken.
|
105160 | } else { |
| 15542 | 86 | innodb_table = dd_table_open_on_name_in_mem(m_name, false); | |
| 15543 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
|
86 | ut_ad(innodb_table->is_temporary()); |
| 15544 | } | ||
| 15545 | |||
| 15546 | 105246 | m_table = innodb_table; | |
| 15547 | |||
| 15548 | 105246 | return (0); | |
| 15549 | } | ||
| 15550 | |||
| 15551 | template int innobase_truncate<dd::Table>::open_table( | ||
| 15552 | dict_table_t *&innodb_table); | ||
| 15553 | template int innobase_truncate<dd::Partition>::open_table( | ||
| 15554 | dict_table_t *&innodb_table); | ||
| 15555 | |||
| 15556 | template <typename Table> | ||
| 15557 | 104330 | int innobase_truncate<Table>::prepare() { | |
| 15558 | 104330 | int error = 0; | |
| 15559 | |||
| 15560 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52165 times.
|
104330 | if (m_table == nullptr) { |
| 15561 | ✗ | error = open_table(m_table); | |
| 15562 | |||
| 15563 | ✗ | if (error != 0) { | |
| 15564 | ✗ | return (error); | |
| 15565 | } | ||
| 15566 | } | ||
| 15567 | |||
| 15568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52165 times.
|
104330 | ut_ad(m_table != nullptr); |
| 15569 | |||
| 15570 |
1/2✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
|
104330 | m_trx = check_trx_exists(m_thd); |
| 15571 |
1/2✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
|
104330 | m_file_per_table = dict_table_is_file_per_table(m_table); |
| 15572 | 104330 | m_flags = m_table->flags; | |
| 15573 | 104330 | m_flags2 = m_table->flags2; | |
| 15574 | |||
| 15575 |
1/2✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
|
104330 | update_create_info_from_table(&m_create_info, m_form); |
| 15576 | |||
| 15577 |
1/2✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
|
104330 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 15578 |
1/2✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
|
104330 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 15579 | |||
| 15580 | /* Get the autoextend_size attribute value for the table being | ||
| 15581 | truncated. This values will be used to create the new table as | ||
| 15582 | part of truncate. */ | ||
| 15583 | 104330 | uint64_t autoextend_size{}; | |
| 15584 | |||
| 15585 |
2/4✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52165 times.
✗ Branch 3 not taken.
|
104330 | dd::Object_id space_id = dd_first_index(m_dd_table)->tablespace_id(); |
| 15586 | |||
| 15587 |
2/2✓ Branch 0 taken 49293 times.
✓ Branch 1 taken 2872 times.
|
104330 | if (m_file_per_table) { |
| 15588 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | dd_get_tablespace_size_option(client, space_id, &autoextend_size); |
| 15589 | } | ||
| 15590 | |||
| 15591 | 104330 | m_create_info.m_implicit_tablespace_autoextend_size = autoextend_size; | |
| 15592 | |||
| 15593 | 104330 | m_create_info.tablespace = nullptr; | |
| 15594 |
3/4✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 52122 times.
|
104330 | if (m_table->is_temporary()) { |
| 15595 | 86 | m_create_info.options |= HA_LEX_CREATE_TMP_TABLE; | |
| 15596 | } else { | ||
| 15597 |
2/2✓ Branch 0 taken 1787 times.
✓ Branch 1 taken 50335 times.
|
104244 | if (m_table->tablespace != nullptr) { |
| 15598 |
1/2✓ Branch 0 taken 1787 times.
✗ Branch 1 not taken.
|
3574 | m_create_info.tablespace = mem_strdup(m_table->tablespace); |
| 15599 | } | ||
| 15600 | } | ||
| 15601 | |||
| 15602 | 104330 | m_create_info.key_block_size = m_form->s->key_block_size; | |
| 15603 | |||
| 15604 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 52145 times.
|
104330 | if (m_table->data_dir_path != nullptr) { |
| 15605 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
40 | m_create_info.data_file_name = mem_strdup(m_table->data_dir_path); |
| 15606 | } else { | ||
| 15607 | 104290 | m_create_info.data_file_name = nullptr; | |
| 15608 | } | ||
| 15609 | |||
| 15610 |
2/2✓ Branch 0 taken 22763 times.
✓ Branch 1 taken 29402 times.
|
104330 | if (m_table->can_be_evicted) { |
| 15611 |
1/2✓ Branch 0 taken 22763 times.
✗ Branch 1 not taken.
|
45526 | dict_sys_mutex_enter(); |
| 15612 |
1/2✓ Branch 0 taken 22763 times.
✗ Branch 1 not taken.
|
45526 | dict_table_ddl_acquire(m_table); |
| 15613 |
1/2✓ Branch 0 taken 22763 times.
✗ Branch 1 not taken.
|
45526 | dict_sys_mutex_exit(); |
| 15614 | } | ||
| 15615 | |||
| 15616 |
2/2✓ Branch 0 taken 51690 times.
✓ Branch 1 taken 475 times.
|
104330 | if (!dict_table_has_autoinc_col(m_table)) { |
| 15617 | 103380 | m_keep_autoinc = false; | |
| 15618 | } | ||
| 15619 | |||
| 15620 | 104330 | return (error); | |
| 15621 | 104330 | } | |
| 15622 | |||
| 15623 | template <typename Table> | ||
| 15624 | 104330 | int innobase_truncate<Table>::truncate() { | |
| 15625 | 104330 | int error = 0; | |
| 15626 | 104330 | bool reset = false; | |
| 15627 | 104330 | uint64_t autoinc = 0; | |
| 15628 | 104330 | uint64_t autoinc_persisted = 0; | |
| 15629 | |||
| 15630 | /* Rename tablespace file to avoid existing file in create. */ | ||
| 15631 |
2/2✓ Branch 0 taken 49293 times.
✓ Branch 1 taken 2872 times.
|
104330 | if (m_file_per_table) { |
| 15632 | 98586 | error = rename_tablespace(); | |
| 15633 | } | ||
| 15634 | |||
| 15635 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52160 times.
|
104324 | DBUG_EXECUTE_IF("ib_truncate_fail_after_rename", error = HA_ERR_GENERIC;); |
| 15636 | |||
| 15637 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52159 times.
|
104324 | if (error != 0) { |
| 15638 | 6 | return (error); | |
| 15639 | } | ||
| 15640 | |||
| 15641 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 52108 times.
|
104318 | if (m_keep_autoinc) { |
| 15642 | 102 | autoinc_persisted = m_table->autoinc_persisted; | |
| 15643 | 102 | autoinc = m_table->autoinc; | |
| 15644 | } | ||
| 15645 | |||
| 15646 | 104318 | dd_table_close(m_table, m_thd, nullptr, false); | |
| 15647 | 104318 | m_table = nullptr; | |
| 15648 | |||
| 15649 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52158 times.
|
104318 | DBUG_EXECUTE_IF("ib_truncate_crash_after_rename", DBUG_SUICIDE();); |
| 15650 | |||
| 15651 | 104316 | error = innobase_basic_ddl::delete_impl(m_thd, m_name, m_dd_table, nullptr); | |
| 15652 | |||
| 15653 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52153 times.
|
104310 | DBUG_EXECUTE_IF("ib_truncate_fail_after_delete", error = HA_ERR_GENERIC;); |
| 15654 | |||
| 15655 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52153 times.
|
104310 | if (error != 0) { |
| 15656 | 4 | return (error); | |
| 15657 | } | ||
| 15658 | |||
| 15659 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52152 times.
|
104306 | DBUG_EXECUTE_IF("ib_truncate_crash_after_drop_old_table", DBUG_SUICIDE();); |
| 15660 | |||
| 15661 |
2/2✓ Branch 0 taken 52109 times.
✓ Branch 1 taken 43 times.
|
104304 | if (m_dd_table->is_persistent()) { |
| 15662 | 104218 | m_dd_table->set_se_private_id(dd::INVALID_OBJECT_ID); | |
| 15663 |
6/10✓ Branch 0 taken 52109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52109 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 52109 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 66745 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 66745 times.
✓ Branch 9 taken 52109 times.
|
341926 | for (auto dd_index : *m_dd_table->indexes()) { |
| 15664 |
2/4✓ Branch 0 taken 66745 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66745 times.
✗ Branch 3 not taken.
|
133490 | dd_index->se_private_data().clear(); |
| 15665 | } | ||
| 15666 | } | ||
| 15667 | |||
| 15668 | 104304 | if (dd_table_is_partitioned(m_dd_table->table()) && | |
| 15669 |
4/6✓ Branch 0 taken 2056 times.
✓ Branch 1 taken 50096 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 52152 times.
|
104304 | m_create_info.tablespace != nullptr && |
| 15670 | ✗ | m_dd_table->tablespace_id() == dd::INVALID_OBJECT_ID) { | |
| 15671 | /* Don't change the tablespace if it's a partitioned table, | ||
| 15672 | so temporarily set the tablespace_id as an explicit one | ||
| 15673 | to make it consistent with info->tablespace */ | ||
| 15674 | ✗ | m_dd_table->set_tablespace_id(dd_first_index(m_dd_table)->tablespace_id()); | |
| 15675 | ✗ | reset = true; | |
| 15676 | } | ||
| 15677 | |||
| 15678 | 104304 | m_trx->in_truncate = true; | |
| 15679 | 104304 | bool inherit_metadata = false; | |
| 15680 | 104304 | if (dd_table_has_instant_cols(m_dd_table->table()) && | |
| 15681 |
8/8✓ Branch 0 taken 55 times.
✓ Branch 1 taken 52097 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 52137 times.
|
104304 | dd_table_is_partitioned(m_dd_table->table()) && !m_table_truncate) { |
| 15682 | /* For a partition table, if this is not a full table truncate, and first | ||
| 15683 | partition is getting truncated, make sure INSTANT metadata is inherited. */ | ||
| 15684 | 30 | inherit_metadata = true; | |
| 15685 | } | ||
| 15686 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 52137 times.
|
104304 | error = innobase_basic_ddl::create_impl( |
| 15687 | 104304 | m_thd, m_name, m_form, &m_create_info, m_dd_table, m_file_per_table, | |
| 15688 | false, true, m_flags, m_flags2, | ||
| 15689 | 30 | inherit_metadata ? &m_dd_table->table() : nullptr); | |
| 15690 | 104292 | m_trx->in_truncate = false; | |
| 15691 | |||
| 15692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52146 times.
|
104292 | if (reset) { |
| 15693 | ✗ | m_dd_table->set_tablespace_id(dd::INVALID_OBJECT_ID); | |
| 15694 | } | ||
| 15695 | |||
| 15696 |
1/2✓ Branch 0 taken 52146 times.
✗ Branch 1 not taken.
|
104292 | if (error == 0) { |
| 15697 | 104292 | dict_sys_mutex_enter(); | |
| 15698 | 104292 | m_table = dict_table_check_if_in_cache_low(m_name); | |
| 15699 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52146 times.
|
104292 | ut_ad(m_table != nullptr); |
| 15700 | 104292 | m_table->acquire(); | |
| 15701 | |||
| 15702 |
2/2✓ Branch 0 taken 50 times.
✓ Branch 1 taken 52096 times.
|
104292 | if (m_keep_autoinc) { |
| 15703 | 100 | m_table->autoinc_persisted = autoinc_persisted; | |
| 15704 | 100 | m_table->autoinc = autoinc; | |
| 15705 | } | ||
| 15706 | |||
| 15707 | 104292 | dict_sys_mutex_exit(); | |
| 15708 | } | ||
| 15709 | |||
| 15710 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52144 times.
|
104292 | DBUG_EXECUTE_IF("ib_truncate_fail_after_create_new_table", |
| 15711 | error = HA_ERR_GENERIC;); | ||
| 15712 | |||
| 15713 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52145 times.
|
104292 | DBUG_EXECUTE_IF("ib_truncate_crash_after_create_new_table", DBUG_SUICIDE();); |
| 15714 | |||
| 15715 | 104290 | return (error); | |
| 15716 | } | ||
| 15717 | |||
| 15718 | template <typename Table> | ||
| 15719 | 98586 | int innobase_truncate<Table>::rename_tablespace() { | |
| 15720 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49293 times.
|
98586 | ut_ad(m_table != nullptr); |
| 15721 |
2/4✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49293 times.
|
98586 | ut_ad(dict_table_is_file_per_table(m_table)); |
| 15722 |
2/4✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49293 times.
|
98586 | ut_ad(!m_table->is_temporary()); |
| 15723 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49293 times.
|
98586 | ut_ad(m_table->trunc_name.m_name == nullptr); |
| 15724 | |||
| 15725 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | uint64_t old_size = mem_heap_get_size(m_table->heap); |
| 15726 | 197172 | char *temp_name = dict_mem_create_temporary_tablename( | |
| 15727 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | m_table->heap, m_table->name.m_name, m_table->id); |
| 15728 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | uint64_t new_size = mem_heap_get_size(m_table->heap); |
| 15729 | |||
| 15730 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | dict_sys_mutex_enter(); |
| 15731 | 98586 | dict_sys->size += new_size - old_size; | |
| 15732 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | dict_sys_mutex_exit(); |
| 15733 | |||
| 15734 | 98586 | std::string new_path; | |
| 15735 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | char *old_path = fil_space_get_first_path(m_table->space); |
| 15736 | |||
| 15737 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 49273 times.
|
98586 | if (DICT_TF_HAS_DATA_DIR(m_table->flags)) { |
| 15738 |
3/6✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | new_path = Fil_path::make_new_path(old_path, temp_name, IBD); |
| 15739 | } else { | ||
| 15740 |
2/4✓ Branch 0 taken 49273 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49273 times.
✗ Branch 3 not taken.
|
98546 | char *ptr = Fil_path::make_ibd_from_table_name(temp_name); |
| 15741 |
1/2✓ Branch 0 taken 49273 times.
✗ Branch 1 not taken.
|
98546 | new_path.assign(ptr); |
| 15742 | 98546 | ut::free(ptr); | |
| 15743 | } | ||
| 15744 | |||
| 15745 | /* New filepath must not exist. */ | ||
| 15746 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | dberr_t err = fil_rename_tablespace_check(m_table->space, old_path, |
| 15747 | new_path.c_str(), false); | ||
| 15748 | |||
| 15749 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | if (err == DB_SUCCESS) { |
| 15750 |
1/2✓ Branch 0 taken 49293 times.
✗ Branch 1 not taken.
|
98586 | dict_sys_mutex_enter(); |
| 15751 |
1/2✓ Branch 0 taken 49290 times.
✗ Branch 1 not taken.
|
98586 | err = fil_rename_tablespace(m_table->space, old_path, temp_name, |
| 15752 | new_path.c_str()); | ||
| 15753 |
1/2✓ Branch 0 taken 49290 times.
✗ Branch 1 not taken.
|
98580 | dict_sys_mutex_exit(); |
| 15754 | |||
| 15755 |
2/2✓ Branch 0 taken 49289 times.
✓ Branch 1 taken 1 times.
|
98580 | if (err == DB_SUCCESS) { |
| 15756 | 98578 | m_table->trunc_name.m_name = temp_name; | |
| 15757 | } | ||
| 15758 | } | ||
| 15759 | |||
| 15760 | 98580 | ut::free(old_path); | |
| 15761 | |||
| 15762 |
1/2✓ Branch 0 taken 49290 times.
✗ Branch 1 not taken.
|
197160 | return (convert_error_code_to_mysql(err, m_table->flags, nullptr)); |
| 15763 | 98580 | } | |
| 15764 | |||
| 15765 | template <typename Table> | ||
| 15766 | 104300 | void innobase_truncate<Table>::cleanup() { | |
| 15767 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52148 times.
|
104300 | if (m_table == nullptr) { |
| 15768 | 4 | m_table = dd_table_open_on_name_in_mem(m_name, false); | |
| 15769 | } | ||
| 15770 | |||
| 15771 |
2/2✓ Branch 0 taken 52148 times.
✓ Branch 1 taken 2 times.
|
104300 | if (m_table != nullptr) { |
| 15772 | 104296 | m_table->trunc_name.m_name = nullptr; | |
| 15773 | } | ||
| 15774 | |||
| 15775 | 104300 | char *tablespace = const_cast<char *>(m_create_info.tablespace); | |
| 15776 | 104300 | char *data_file_name = const_cast<char *>(m_create_info.data_file_name); | |
| 15777 | |||
| 15778 | 104300 | ut::free(tablespace); | |
| 15779 | 104300 | ut::free(data_file_name); | |
| 15780 | 104300 | } | |
| 15781 | |||
| 15782 | template <typename Table> | ||
| 15783 | 104286 | int innobase_truncate<Table>::load_fk() { | |
| 15784 |
5/7✓ Branch 0 taken 2055 times.
✓ Branch 1 taken 50088 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2055 times.
✓ Branch 4 taken 50088 times.
✓ Branch 5 taken 2055 times.
✗ Branch 6 not taken.
|
104286 | if (dd_table_is_partitioned(m_dd_table->table())) { |
| 15785 | 4110 | return (0); | |
| 15786 | } | ||
| 15787 | |||
| 15788 | 100176 | int error = 0; | |
| 15789 |
1/2✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
|
100176 | dict_names_t fk_tables; |
| 15790 |
1/2✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
|
100176 | dd::cache::Dictionary_client *client = dd::get_dd_client(m_thd); |
| 15791 |
1/2✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
|
100176 | dd::cache::Dictionary_client::Auto_releaser releaser(client); |
| 15792 | |||
| 15793 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50088 times.
|
100176 | ut_ad(m_table != nullptr); |
| 15794 | 100176 | error = | |
| 15795 |
1/2✓ Branch 0 taken 50088 times.
✗ Branch 1 not taken.
|
100176 | dd_table_check_for_child(client, m_table->name.m_name, nullptr, m_table, |
| 15796 | true, DICT_ERR_IGNORE_NONE, &fk_tables); | ||
| 15797 | |||
| 15798 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50088 times.
|
100176 | ut_ad(fk_tables.empty()); |
| 15799 | |||
| 15800 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50088 times.
|
100176 | if (error != DB_SUCCESS) { |
| 15801 | ✗ | push_warning_printf(m_thd, Sql_condition::SL_WARNING, | |
| 15802 | HA_ERR_CANNOT_ADD_FOREIGN, | ||
| 15803 | "Truncate table '%s' failed to load some" | ||
| 15804 | " foreign key constraints.", | ||
| 15805 | m_name); | ||
| 15806 | } else { | ||
| 15807 | 100176 | error = 0; | |
| 15808 | } | ||
| 15809 | |||
| 15810 | 100176 | return (error); | |
| 15811 | } | ||
| 15812 | |||
| 15813 | template <typename Table> | ||
| 15814 | 104330 | int innobase_truncate<Table>::exec() { | |
| 15815 | 104330 | int error = 0; | |
| 15816 | |||
| 15817 | 104330 | error = prepare(); | |
| 15818 | |||
| 15819 |
1/2✓ Branch 0 taken 52165 times.
✗ Branch 1 not taken.
|
104330 | if (error == 0) { |
| 15820 | 104330 | error = truncate(); | |
| 15821 | } | ||
| 15822 | |||
| 15823 | 104300 | cleanup(); | |
| 15824 | |||
| 15825 |
2/2✓ Branch 0 taken 52143 times.
✓ Branch 1 taken 7 times.
|
104300 | if (error == 0) { |
| 15826 | 104286 | error = load_fk(); | |
| 15827 | } | ||
| 15828 | |||
| 15829 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52149 times.
|
104300 | DBUG_EXECUTE_IF("ib_truncate_crash_after_innodb_complete", DBUG_SUICIDE();); |
| 15830 | |||
| 15831 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 52148 times.
|
104298 | DBUG_EXECUTE_IF("ib_truncate_rollback_test", error = HA_ERR_GENERIC;); |
| 15832 | |||
| 15833 | 104298 | return (error); | |
| 15834 | } | ||
| 15835 | |||
| 15836 | template int innobase_truncate<dd::Table>::exec(); | ||
| 15837 | template int innobase_truncate<dd::Partition>::exec(); | ||
| 15838 | |||
| 15839 | /** Check if a column is the only column in an index. | ||
| 15840 | @param[in] index data dictionary index | ||
| 15841 | @param[in] column the column to look for | ||
| 15842 | @return whether the column is the only column in the index */ | ||
| 15843 | 32 | static bool dd_is_only_column(const dd::Index *index, | |
| 15844 | const dd::Column *column) { | ||
| 15845 |
3/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1 times.
|
63 | return (index->elements().size() == 1 && |
| 15846 |
6/10✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 31 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 29 times.
✓ Branch 9 taken 2 times.
|
63 | &(*index->elements().begin())->column() == column); |
| 15847 | } | ||
| 15848 | |||
| 15849 | /** Add hidden columns and indexes to an InnoDB table definition. | ||
| 15850 | @param[in,out] dd_table data dictionary cache object | ||
| 15851 | @return error number | ||
| 15852 | @retval 0 on success */ | ||
| 15853 | 626007 | int ha_innobase::get_extra_columns_and_keys(const HA_CREATE_INFO *, | |
| 15854 | const List<Create_field> *, | ||
| 15855 | const KEY *, uint, | ||
| 15856 | dd::Table *dd_table) { | ||
| 15857 |
1/2✓ Branch 0 taken 626023 times.
✗ Branch 1 not taken.
|
626007 | DBUG_TRACE; |
| 15858 |
1/2✓ Branch 0 taken 626019 times.
✗ Branch 1 not taken.
|
626023 | THD *thd = ha_thd(); |
| 15859 | 626019 | dd::Index *primary = nullptr; | |
| 15860 | 626019 | bool has_fulltext = false; | |
| 15861 | 626019 | const dd::Index *fts_doc_id_index = nullptr; | |
| 15862 | |||
| 15863 |
6/10✓ Branch 0 taken 626012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 626018 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 626014 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1355315 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1355315 times.
✓ Branch 9 taken 626018 times.
|
1981334 | for (dd::Index *i : *dd_table->indexes()) { |
| 15864 | /* The name "PRIMARY" is reserved for the PRIMARY KEY */ | ||
| 15865 |
4/8✓ Branch 0 taken 1355315 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1355315 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1355315 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1355315 times.
|
1355315 | ut_ad((i->type() == dd::Index::IT_PRIMARY) == |
| 15866 | !my_strcasecmp(system_charset_info, i->name().c_str(), | ||
| 15867 | primary_key_name)); | ||
| 15868 | |||
| 15869 |
4/6✓ Branch 0 taken 1355315 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1355315 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
✓ Branch 5 taken 1355256 times.
|
1355315 | if (!my_strcasecmp(system_charset_info, i->name().c_str(), |
| 15870 | FTS_DOC_ID_INDEX_NAME)) { | ||
| 15871 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | ut_ad(!fts_doc_id_index); |
| 15872 |
2/4✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 59 times.
|
59 | ut_ad(i->type() != dd::Index::IT_PRIMARY); |
| 15873 | 59 | fts_doc_id_index = i; | |
| 15874 | } | ||
| 15875 | |||
| 15876 |
4/8✓ Branch 0 taken 1355315 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1226 times.
✓ Branch 5 taken 1351779 times.
✓ Branch 6 taken 2310 times.
✗ Branch 7 not taken.
|
1355315 | switch (i->algorithm()) { |
| 15877 | ✗ | case dd::Index::IA_SE_SPECIFIC: | |
| 15878 | ✗ | ut_d(ut_error); | |
| 15879 | ut_o(break); | ||
| 15880 | ✗ | case dd::Index::IA_HASH: | |
| 15881 | /* This is currently blocked | ||
| 15882 | by ha_innobase::is_index_algorithm_supported(). */ | ||
| 15883 | ✗ | ut_d(ut_error); | |
| 15884 | ut_o(break); | ||
| 15885 | 1226 | case dd::Index::IA_RTREE: | |
| 15886 |
2/4✓ Branch 0 taken 1226 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1226 times.
✗ Branch 3 not taken.
|
1226 | if (i->type() == dd::Index::IT_SPATIAL) { |
| 15887 | 1226 | continue; | |
| 15888 | } | ||
| 15889 | ✗ | ut_d(ut_error); | |
| 15890 | ut_o(break); | ||
| 15891 | 1351779 | case dd::Index::IA_BTREE: | |
| 15892 |
4/7✓ Branch 0 taken 1351779 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 455694 times.
✓ Branch 3 taken 419273 times.
✓ Branch 4 taken 476812 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
1351779 | switch (i->type()) { |
| 15893 | 455694 | case dd::Index::IT_PRIMARY: | |
| 15894 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 455694 times.
|
455694 | ut_ad(!primary); |
| 15895 |
4/8✓ Branch 0 taken 455694 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 455694 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 455694 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 455694 times.
|
455694 | ut_ad(i == *dd_table->indexes()->begin()); |
| 15896 | 455694 | primary = i; | |
| 15897 | 455694 | continue; | |
| 15898 | 419273 | case dd::Index::IT_UNIQUE: | |
| 15899 |
7/8✓ Branch 0 taken 38995 times.
✓ Branch 1 taken 380278 times.
✓ Branch 2 taken 38995 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37366 times.
✓ Branch 5 taken 1629 times.
✓ Branch 6 taken 37366 times.
✓ Branch 7 taken 381907 times.
|
419273 | if (primary == nullptr && i->is_candidate_key()) { |
| 15900 | 37366 | primary = i; | |
| 15901 |
4/8✓ Branch 0 taken 37366 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37366 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37366 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 37366 times.
|
37366 | ut_ad(*dd_table->indexes()->begin() == i); |
| 15902 | } | ||
| 15903 | 419273 | continue; | |
| 15904 | 476812 | case dd::Index::IT_MULTIPLE: | |
| 15905 | 476812 | continue; | |
| 15906 | ✗ | case dd::Index::IT_FULLTEXT: | |
| 15907 | case dd::Index::IT_SPATIAL: | ||
| 15908 | ✗ | ut_d(ut_error); | |
| 15909 | } | ||
| 15910 | ✗ | break; | |
| 15911 | 2310 | case dd::Index::IA_FULLTEXT: | |
| 15912 |
2/4✓ Branch 0 taken 2310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2310 times.
✗ Branch 3 not taken.
|
2310 | if (i->type() == dd::Index::IT_FULLTEXT) { |
| 15913 | 2310 | has_fulltext = true; | |
| 15914 | 2310 | continue; | |
| 15915 | } | ||
| 15916 | ✗ | ut_d(ut_error); | |
| 15917 | ut_o(break); | ||
| 15918 | } | ||
| 15919 | |||
| 15920 | ✗ | my_error(ER_UNSUPPORTED_INDEX_ALGORITHM, MYF(0), i->name().c_str()); | |
| 15921 | ✗ | return ER_UNSUPPORTED_INDEX_ALGORITHM; | |
| 15922 | } | ||
| 15923 | |||
| 15924 |
2/2✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 624858 times.
|
626018 | if (has_fulltext) { |
| 15925 | /* Add FTS_DOC_ID_INDEX(FTS_DOC_ID) if needed */ | ||
| 15926 | const dd::Column *fts_doc_id = | ||
| 15927 |
1/2✓ Branch 0 taken 1160 times.
✗ Branch 1 not taken.
|
1160 | dd_find_column(dd_table, FTS_DOC_ID_COL_NAME); |
| 15928 | |||
| 15929 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1126 times.
|
1160 | if (fts_doc_id_index) { |
| 15930 |
3/6✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
34 | switch (fts_doc_id_index->type()) { |
| 15931 | ✗ | case dd::Index::IT_PRIMARY: | |
| 15932 | /* PRIMARY!=FTS_DOC_ID_INDEX */ | ||
| 15933 | ✗ | ut_ad(!"wrong fts_doc_id_index"); | |
| 15934 | [[fallthrough]]; | ||
| 15935 | case dd::Index::IT_UNIQUE: | ||
| 15936 | /* We already checked for this. */ | ||
| 15937 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
32 | ut_ad(fts_doc_id_index->algorithm() == dd::Index::IA_BTREE); |
| 15938 |
3/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 3 times.
|
32 | if (dd_is_only_column(fts_doc_id_index, fts_doc_id)) { |
| 15939 | 29 | break; | |
| 15940 | } | ||
| 15941 | [[fallthrough]]; | ||
| 15942 | case dd::Index::IT_MULTIPLE: | ||
| 15943 | case dd::Index::IT_FULLTEXT: | ||
| 15944 | case dd::Index::IT_SPATIAL: | ||
| 15945 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | my_error(ER_INNODB_FT_WRONG_DOCID_INDEX, MYF(0), |
| 15946 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | fts_doc_id_index->name().c_str()); |
| 15947 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_NAME_FOR_INDEX, |
| 15948 | " InnoDB: Index name " FTS_DOC_ID_INDEX_NAME | ||
| 15949 | " is reserved" | ||
| 15950 | " for UNIQUE INDEX(" FTS_DOC_ID_COL_NAME | ||
| 15951 | ") for " | ||
| 15952 | " FULLTEXT Document ID indexing."); | ||
| 15953 | 5 | return ER_INNODB_FT_WRONG_DOCID_INDEX; | |
| 15954 | } | ||
| 15955 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | ut_ad(fts_doc_id); |
| 15956 | } | ||
| 15957 | |||
| 15958 |
2/2✓ Branch 0 taken 86 times.
✓ Branch 1 taken 1069 times.
|
1155 | if (fts_doc_id) { |
| 15959 |
1/2✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
|
86 | if (fts_doc_id->type() != dd::enum_column_types::LONGLONG || |
| 15960 |
7/8✓ Branch 0 taken 74 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 74 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 18 times.
✓ Branch 7 taken 68 times.
|
154 | fts_doc_id->is_nullable() || |
| 15961 |
3/6✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 68 times.
|
68 | fts_doc_id->name() != FTS_DOC_ID_COL_NAME) { |
| 15962 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | my_error(ER_INNODB_FT_WRONG_DOCID_COLUMN, MYF(0), |
| 15963 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | fts_doc_id->name().c_str()); |
| 15964 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_COLUMN_NAME, |
| 15965 | " InnoDB: Column name " FTS_DOC_ID_COL_NAME | ||
| 15966 | " is reserved for" | ||
| 15967 | " FULLTEXT Document ID indexing."); | ||
| 15968 | 18 | return ER_INNODB_FT_WRONG_DOCID_COLUMN; | |
| 15969 | } | ||
| 15970 | } else { | ||
| 15971 | /* Add hidden FTS_DOC_ID column */ | ||
| 15972 |
1/2✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
|
1069 | dd::Column *col = dd_table->add_column(); |
| 15973 |
1/2✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
|
1069 | col->set_hidden(dd::Column::enum_hidden_type::HT_HIDDEN_SE); |
| 15974 |
2/4✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1069 times.
✗ Branch 3 not taken.
|
1069 | col->set_name(FTS_DOC_ID_COL_NAME); |
| 15975 |
1/2✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
|
1069 | col->set_type(dd::enum_column_types::LONGLONG); |
| 15976 |
1/2✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
|
1069 | col->set_nullable(false); |
| 15977 |
1/2✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
|
1069 | col->set_unsigned(true); |
| 15978 |
1/2✓ Branch 0 taken 1069 times.
✗ Branch 1 not taken.
|
1069 | col->set_collation_id(1); |
| 15979 | 1069 | fts_doc_id = col; | |
| 15980 | } | ||
| 15981 | |||
| 15982 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1137 times.
|
1137 | ut_ad(fts_doc_id); |
| 15983 | |||
| 15984 |
2/2✓ Branch 0 taken 1109 times.
✓ Branch 1 taken 28 times.
|
1137 | if (fts_doc_id_index == nullptr) { |
| 15985 |
2/4✓ Branch 0 taken 1109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1109 times.
✗ Branch 3 not taken.
|
1109 | dd_set_hidden_unique_index(dd_table->add_index(), FTS_DOC_ID_INDEX_NAME, |
| 15986 | fts_doc_id); | ||
| 15987 | } | ||
| 15988 | } | ||
| 15989 | |||
| 15990 |
2/2✓ Branch 0 taken 132944 times.
✓ Branch 1 taken 493051 times.
|
625995 | if (primary == nullptr) { |
| 15991 |
1/2✓ Branch 0 taken 132960 times.
✗ Branch 1 not taken.
|
132944 | dd::Column *db_row_id = dd_add_hidden_column( |
| 15992 | dd_table, "DB_ROW_ID", DATA_ROW_ID_LEN, dd::enum_column_types::INT24); | ||
| 15993 | |||
| 15994 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 132958 times.
|
132960 | if (db_row_id == nullptr) { |
| 15995 | 2 | return ER_WRONG_COLUMN_NAME; | |
| 15996 | } | ||
| 15997 | |||
| 15998 |
2/4✓ Branch 0 taken 132954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132957 times.
✗ Branch 3 not taken.
|
132958 | primary = dd_set_hidden_unique_index(dd_table->add_first_index(), |
| 15999 | primary_key_name, db_row_id); | ||
| 16000 | } | ||
| 16001 | |||
| 16002 | /* Add PRIMARY KEY columns to each secondary index, including: | ||
| 16003 | 1. all PRIMARY KEY column prefixes | ||
| 16004 | 2. full PRIMARY KEY columns which don't exist in the secondary index */ | ||
| 16005 | |||
| 16006 | std::vector<const dd::Index_element *, | ||
| 16007 | ut::allocator<const dd::Index_element *>> | ||
| 16008 |
1/2✓ Branch 0 taken 625989 times.
✗ Branch 1 not taken.
|
1252006 | pk_elements; |
| 16009 | |||
| 16010 |
6/10✓ Branch 0 taken 625993 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 625988 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 625994 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1489319 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1489307 times.
✓ Branch 9 taken 625993 times.
|
2115308 | for (dd::Index *index : *dd_table->indexes()) { |
| 16011 |
2/2✓ Branch 0 taken 625992 times.
✓ Branch 1 taken 863327 times.
|
1489319 | if (index == primary) { |
| 16012 | 625992 | continue; | |
| 16013 | } | ||
| 16014 | |||
| 16015 | 863327 | pk_elements.clear(); | |
| 16016 |
6/10✓ Branch 0 taken 863327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 863327 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 863327 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1047345 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1047345 times.
✓ Branch 9 taken 863327 times.
|
1910672 | for (const dd::Index_element *e : primary->elements()) { |
| 16017 |
5/6✓ Branch 0 taken 1047345 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029333 times.
✓ Branch 3 taken 18012 times.
✓ Branch 4 taken 914568 times.
✓ Branch 5 taken 114765 times.
|
2076678 | if (e->is_prefix() || |
| 16018 |
1/2✓ Branch 0 taken 1029333 times.
✗ Branch 1 not taken.
|
1029333 | std::search_n( |
| 16019 |
4/8✓ Branch 0 taken 1029333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1029333 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1029333 times.
✗ Branch 7 not taken.
|
1029333 | index->elements().begin(), index->elements().end(), 1, e, |
| 16020 | 1591185 | [](const dd::Index_element *ie, const dd::Index_element *e) { | |
| 16021 | 1591185 | return (&ie->column() == &e->column()); | |
| 16022 |
4/6✓ Branch 0 taken 1029333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1029333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 932580 times.
✓ Branch 5 taken 114765 times.
|
3106011 | }) == index->elements().end()) { |
| 16023 |
1/2✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
|
932580 | pk_elements.push_back(e); |
| 16024 | } | ||
| 16025 | } | ||
| 16026 | |||
| 16027 |
2/2✓ Branch 0 taken 932580 times.
✓ Branch 1 taken 863327 times.
|
1795907 | for (const dd::Index_element *e : pk_elements) { |
| 16028 |
2/4✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932580 times.
✗ Branch 3 not taken.
|
932580 | auto ie = index->add_element(const_cast<dd::Column *>(&e->column())); |
| 16029 |
1/2✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
|
932580 | ie->set_hidden(true); |
| 16030 |
2/4✓ Branch 0 taken 932580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 932580 times.
✗ Branch 3 not taken.
|
932580 | ie->set_order(e->order()); |
| 16031 | } | ||
| 16032 | } | ||
| 16033 | |||
| 16034 | /* Add the InnoDB system columns DB_TRX_ID, DB_ROLL_PTR. */ | ||
| 16035 |
1/2✓ Branch 0 taken 625998 times.
✗ Branch 1 not taken.
|
625993 | dd::Column *db_trx_id = dd_add_hidden_column( |
| 16036 | dd_table, "DB_TRX_ID", DATA_TRX_ID_LEN, dd::enum_column_types::INT24); | ||
| 16037 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 625995 times.
|
625998 | if (db_trx_id == nullptr) { |
| 16038 | 3 | return ER_WRONG_COLUMN_NAME; | |
| 16039 | } | ||
| 16040 | |||
| 16041 | dd::Column *db_roll_ptr = | ||
| 16042 |
1/2✓ Branch 0 taken 625996 times.
✗ Branch 1 not taken.
|
625995 | dd_add_hidden_column(dd_table, "DB_ROLL_PTR", DATA_ROLL_PTR_LEN, |
| 16043 | dd::enum_column_types::LONGLONG); | ||
| 16044 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 625993 times.
|
625996 | if (db_roll_ptr == nullptr) { |
| 16045 | 3 | return ER_WRONG_COLUMN_NAME; | |
| 16046 | } | ||
| 16047 | |||
| 16048 |
1/2✓ Branch 0 taken 625993 times.
✗ Branch 1 not taken.
|
625993 | dd_add_hidden_element(primary, db_trx_id); |
| 16049 |
1/2✓ Branch 0 taken 625992 times.
✗ Branch 1 not taken.
|
625993 | dd_add_hidden_element(primary, db_roll_ptr); |
| 16050 | |||
| 16051 | /* Add all non-virtual columns to the clustered index, | ||
| 16052 | unless they already part of the PRIMARY KEY. */ | ||
| 16053 | |||
| 16054 | 625992 | for (const dd::Column *c : | |
| 16055 |
6/10✓ Branch 0 taken 625993 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 625993 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 625992 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6503069 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6503068 times.
✓ Branch 9 taken 625992 times.
|
7755059 | const_cast<const dd::Table *>(dd_table)->columns()) { |
| 16056 |
8/10✓ Branch 0 taken 6503070 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5117063 times.
✓ Branch 3 taken 1386007 times.
✓ Branch 4 taken 5117060 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9220 times.
✓ Branch 7 taken 5107840 times.
✓ Branch 8 taken 1395229 times.
✓ Branch 9 taken 5107838 times.
|
6503069 | if (c->is_se_hidden() || c->is_virtual()) { |
| 16057 | 1395229 | continue; | |
| 16058 | } | ||
| 16059 | |||
| 16060 |
5/10✓ Branch 0 taken 5107847 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5107838 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5107847 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5107845 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5107845 times.
✗ Branch 9 not taken.
|
5107846 | if (std::search_n(primary->elements().begin(), primary->elements().end(), 1, |
| 16061 | 70101815 | c, [](const dd::Index_element *e, const dd::Column *c) { | |
| 16062 |
4/4✓ Branch 0 taken 6291892 times.
✓ Branch 1 taken 63809933 times.
✓ Branch 2 taken 809614 times.
✓ Branch 3 taken 5482278 times.
|
70101815 | return (!e->is_prefix() && &e->column() == c); |
| 16063 |
4/6✓ Branch 0 taken 5107840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5107846 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4298231 times.
✓ Branch 5 taken 809613 times.
|
10215683 | }) == primary->elements().end()) { |
| 16064 |
1/2✓ Branch 0 taken 4298233 times.
✗ Branch 1 not taken.
|
4298231 | dd_add_hidden_element(primary, c); |
| 16065 | } | ||
| 16066 | } | ||
| 16067 | |||
| 16068 | 625992 | return 0; | |
| 16069 | 626023 | } | |
| 16070 | |||
| 16071 | /** Set Engine specific data to dd::Table object for upgrade. | ||
| 16072 | @param[in,out] thd thread handle | ||
| 16073 | @param[in] db_name database name | ||
| 16074 | @param[in] table_name table name | ||
| 16075 | @param[in,out] dd_table data dictionary cache object | ||
| 16076 | @return 0 on success, non-zero on failure */ | ||
| 16077 | 3101 | bool ha_innobase::upgrade_table(THD *thd, const char *db_name, | |
| 16078 | const char *table_name, dd::Table *dd_table) { | ||
| 16079 | 3101 | return (dd_upgrade_table(thd, db_name, table_name, dd_table, table)); | |
| 16080 | } | ||
| 16081 | |||
| 16082 | /** Get storage-engine private data for a data dictionary table. | ||
| 16083 | @param[in,out] dd_table data dictionary table definition | ||
| 16084 | @param reset reset counters | ||
| 16085 | @retval true an error occurred | ||
| 16086 | @retval false success */ | ||
| 16087 | 24500 | bool ha_innobase::get_se_private_data(dd::Table *dd_table, bool reset) { | |
| 16088 | static uint n_tables = 0; | ||
| 16089 | static uint n_indexes = 0; | ||
| 16090 | static uint n_pages = 4; | ||
| 16091 | |||
| 16092 | /* Reset counters on second create during upgrade. */ | ||
| 16093 |
2/2✓ Branch 0 taken 11960 times.
✓ Branch 1 taken 12540 times.
|
24500 | if (reset) { |
| 16094 | 11960 | n_tables = 0; | |
| 16095 | 11960 | n_indexes = 0; | |
| 16096 | 11960 | n_pages = 4; | |
| 16097 | // Also need to reset the set of DD table ids. | ||
| 16098 | 11960 | dict_sys_t::s_dd_table_ids.clear(); | |
| 16099 | } | ||
| 16100 | #ifdef UNIV_DEBUG | ||
| 16101 | 24500 | const uint n_indexes_old = n_indexes; | |
| 16102 | #endif | ||
| 16103 | |||
| 16104 |
1/2✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
|
24500 | DBUG_TRACE; |
| 16105 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24500 times.
|
24500 | assert(dd_table != nullptr); |
| 16106 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24500 times.
|
24500 | assert(n_tables < innodb_dd_table_size); |
| 16107 | |||
| 16108 |
3/6✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24500 times.
✗ Branch 5 not taken.
|
24500 | if ((*(const_cast<const dd::Table *>(dd_table))->columns().begin()) |
| 16109 |
3/4✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6840 times.
✓ Branch 3 taken 17660 times.
|
24500 | ->is_auto_increment()) { |
| 16110 |
2/4✓ Branch 0 taken 6840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6840 times.
✗ Branch 3 not taken.
|
6840 | dd_set_autoinc(dd_table->se_private_data(), 0); |
| 16111 | } | ||
| 16112 | |||
| 16113 | #ifdef UNIV_DEBUG | ||
| 16114 | { | ||
| 16115 | /* These tables must not be partitioned. */ | ||
| 16116 |
2/4✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24500 times.
|
24500 | assert(dd_table->partitions()->empty()); |
| 16117 | } | ||
| 16118 | |||
| 16119 | 24500 | const innodb_dd_table_t &data = innodb_dd_table[n_tables]; | |
| 16120 | #endif | ||
| 16121 | |||
| 16122 |
2/4✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24500 times.
|
24500 | assert(dd_table->name() == data.name); |
| 16123 | |||
| 16124 |
1/2✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
|
24500 | dd_table->set_se_private_id(++n_tables); |
| 16125 |
1/2✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
|
24500 | dd_table->set_tablespace_id(dict_sys_t::s_dd_dict_space_id); |
| 16126 | |||
| 16127 | /* Set the table id for each column to be conform with the | ||
| 16128 | implementation in dd_write_table(). */ | ||
| 16129 |
6/10✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24500 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 203640 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 203640 times.
✓ Branch 9 taken 24500 times.
|
228140 | for (auto dd_column : *dd_table->table().columns()) { |
| 16130 |
3/6✓ Branch 0 taken 203640 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 203640 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 203640 times.
✗ Branch 5 not taken.
|
203640 | dd_column->se_private_data().set(dd_index_key_strings[DD_TABLE_ID], |
| 16131 | n_tables); | ||
| 16132 | } | ||
| 16133 | |||
| 16134 |
6/10✓ Branch 0 taken 24500 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24500 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24500 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 50340 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 50340 times.
✓ Branch 9 taken 24500 times.
|
74840 | for (dd::Index *i : *dd_table->indexes()) { |
| 16135 |
1/2✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
|
50340 | i->set_tablespace_id(dict_sys_t::s_dd_dict_space_id); |
| 16136 | |||
| 16137 |
3/4✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 926 times.
✓ Branch 3 taken 49414 times.
|
50340 | if (fsp_is_inode_page(n_pages)) { |
| 16138 | 926 | ++n_pages; | |
| 16139 |
2/4✓ Branch 0 taken 926 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 926 times.
|
926 | ut_ad(!fsp_is_inode_page(n_pages)); |
| 16140 | } | ||
| 16141 | |||
| 16142 |
1/2✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
|
50340 | dd::Properties &p = i->se_private_data(); |
| 16143 | |||
| 16144 |
2/4✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
|
50340 | p.set(dd_index_key_strings[DD_INDEX_ROOT], n_pages++); |
| 16145 |
2/4✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
|
50340 | p.set(dd_index_key_strings[DD_INDEX_ID], ++n_indexes); |
| 16146 |
2/4✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
|
50340 | p.set(dd_index_key_strings[DD_INDEX_TRX_ID], 0); |
| 16147 |
2/4✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
|
50340 | p.set(dd_index_key_strings[DD_INDEX_SPACE_ID], dict_sys_t::s_dict_space_id); |
| 16148 |
2/4✓ Branch 0 taken 50340 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50340 times.
✗ Branch 3 not taken.
|
50340 | p.set(dd_index_key_strings[DD_TABLE_ID], n_tables); |
| 16149 | } | ||
| 16150 | |||
| 16151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24500 times.
|
24500 | assert(n_indexes - n_indexes_old == data.n_indexes); |
| 16152 | |||
| 16153 | 24500 | return false; | |
| 16154 | 24500 | } | |
| 16155 | |||
| 16156 | /** Create an InnoDB table. | ||
| 16157 | @param[in] name table name in filename-safe encoding | ||
| 16158 | @param[in] form table structure | ||
| 16159 | @param[in] create_info more information on the table | ||
| 16160 | @param[in,out] table_def dd::Table describing table to be | ||
| 16161 | created. Can be adjusted by SE, the changes will be saved into data-dictionary | ||
| 16162 | at statement commit time. | ||
| 16163 | @return error number | ||
| 16164 | @retval 0 on success */ | ||
| 16165 | 403769 | int ha_innobase::create(const char *name, TABLE *form, | |
| 16166 | HA_CREATE_INFO *create_info, dd::Table *table_def) { | ||
| 16167 | 403769 | THD *thd = ha_thd(); | |
| 16168 | |||
| 16169 | 403769 | adjust_encryption_options(create_info, table_def); | |
| 16170 | |||
| 16171 |
2/2✓ Branch 0 taken 50115 times.
✓ Branch 1 taken 353654 times.
|
403769 | if (thd_sql_command(thd) == SQLCOM_TRUNCATE) { |
| 16172 | 50115 | return (truncate_impl(name, form, table_def)); | |
| 16173 | } | ||
| 16174 | |||
| 16175 | 353654 | trx_t *trx = check_trx_exists(thd); | |
| 16176 | |||
| 16177 |
2/2✓ Branch 0 taken 124787 times.
✓ Branch 1 taken 228867 times.
|
353654 | if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { |
| 16178 | 124787 | innobase_register_trx(ht, thd, trx); | |
| 16179 | } | ||
| 16180 | |||
| 16181 | /* Determine if this CREATE TABLE will be making a file-per-table | ||
| 16182 | tablespace. Note that "srv_file_per_table" is not under | ||
| 16183 | dict_sys mutex protection, and could be changed while creating the | ||
| 16184 | table. So we read the current value here and make all further | ||
| 16185 | decisions based on this. */ | ||
| 16186 | 353653 | return (innobase_basic_ddl::create_impl(ha_thd(), name, form, create_info, | |
| 16187 | table_def, srv_file_per_table, true, | ||
| 16188 | 353620 | false, 0, 0, nullptr)); | |
| 16189 | } | ||
| 16190 | |||
| 16191 | /** Discards or imports an InnoDB tablespace. | ||
| 16192 | @param[in] discard true if discard, else import | ||
| 16193 | @param[in,out] table_def dd::Table describing table which | ||
| 16194 | tablespace is to be imported or discarded. Can be adjusted by SE, | ||
| 16195 | the changes will be saved into the data-dictionary at statement | ||
| 16196 | commit time. | ||
| 16197 | @return 0 == success, -1 == error */ | ||
| 16198 | |||
| 16199 | 1721 | int ha_innobase::discard_or_import_tablespace(bool discard, | |
| 16200 | dd::Table *table_def) { | ||
| 16201 |
1/2✓ Branch 0 taken 1721 times.
✗ Branch 1 not taken.
|
1721 | DBUG_TRACE; |
| 16202 | |||
| 16203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1721 times.
|
1721 | ut_a(m_prebuilt->trx != nullptr); |
| 16204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1721 times.
|
1721 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 16205 |
3/6✓ Branch 0 taken 1721 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1721 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1721 times.
|
1721 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 16206 | |||
| 16207 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1721 times.
|
1721 | if (high_level_read_only) { |
| 16208 | ✗ | return HA_ERR_TABLE_READONLY; | |
| 16209 | } | ||
| 16210 | |||
| 16211 | 1721 | dict_table_t *dict_table = m_prebuilt->table; | |
| 16212 | |||
| 16213 |
3/4✓ Branch 0 taken 1721 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1714 times.
|
1721 | if (dict_table->is_temporary()) { |
| 16214 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, |
| 16215 | ER_CANNOT_DISCARD_TEMPORARY_TABLE); | ||
| 16216 | |||
| 16217 | 7 | return HA_ERR_TABLE_NEEDS_UPGRADE; | |
| 16218 | } | ||
| 16219 | |||
| 16220 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1714 times.
|
1714 | if (dict_table->space == TRX_SYS_SPACE) { |
| 16221 | ✗ | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 16222 | ER_TABLE_IN_SYSTEM_TABLESPACE, dict_table->name.m_name); | ||
| 16223 | |||
| 16224 | ✗ | return HA_ERR_TABLE_NEEDS_UPGRADE; | |
| 16225 | } | ||
| 16226 | |||
| 16227 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1712 times.
|
1714 | if (DICT_TF_HAS_SHARED_SPACE(dict_table->flags)) { |
| 16228 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | my_printf_error(ER_NOT_ALLOWED_COMMAND, |
| 16229 | "InnoDB: Cannot %s table `%s` because it is in" | ||
| 16230 | " a general tablespace. It must be file-per-table.", | ||
| 16231 | MYF(0), discard ? "discard" : "import", | ||
| 16232 | dict_table->name.m_name); | ||
| 16233 | |||
| 16234 | 2 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 16235 | } | ||
| 16236 | |||
| 16237 |
1/2✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
|
1712 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 16238 | |||
| 16239 |
2/4✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1712 times.
|
1712 | if (trx_in_innodb.is_aborted()) { |
| 16240 | ✗ | innobase_rollback(ht, m_user_thd, false); | |
| 16241 | |||
| 16242 | ✗ | return convert_error_code_to_mysql(DB_FORCED_ABORT, 0, m_user_thd); | |
| 16243 | } | ||
| 16244 | |||
| 16245 |
1/2✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
|
1712 | trx_start_if_not_started(m_prebuilt->trx, true, UT_LOCATION_HERE); |
| 16246 | |||
| 16247 | /* Obtain an exclusive lock on the table. */ | ||
| 16248 |
2/2✓ Branch 0 taken 894 times.
✓ Branch 1 taken 818 times.
|
1712 | dberr_t err = row_mysql_lock_table( |
| 16249 |
1/2✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
|
1712 | m_prebuilt->trx, dict_table, LOCK_X, |
| 16250 | discard ? "setting table lock for DISCARD TABLESPACE" | ||
| 16251 | : "setting table lock for IMPORT TABLESPACE"); | ||
| 16252 | |||
| 16253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1712 times.
|
1712 | if (err != DB_SUCCESS) { |
| 16254 | /* unable to lock the table: do nothing */ | ||
| 16255 | /* purecov: begin inspected */ | ||
| 16256 | ✗ | return convert_error_code_to_mysql(err, dict_table->flags, nullptr); | |
| 16257 | /* purecov: end */ | ||
| 16258 | } | ||
| 16259 | |||
| 16260 | /* Concurrent clone operation is not supported. */ | ||
| 16261 | Clone_notify notifier(Clone_notify::Type::SPACE_IMPORT, | ||
| 16262 |
1/2✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
|
1712 | dict_sys_t::s_invalid_space_id, false); |
| 16263 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1710 times.
|
1712 | if (notifier.failed()) { |
| 16264 | 2 | return notifier.get_error(); | |
| 16265 | } | ||
| 16266 | |||
| 16267 |
2/2✓ Branch 0 taken 893 times.
✓ Branch 1 taken 817 times.
|
1710 | if (discard) { |
| 16268 | /* Discarding an already discarded tablespace should be an | ||
| 16269 | idempotent operation. Also, if the .ibd file is missing the | ||
| 16270 | user may want to set the DISCARD flag in order to IMPORT | ||
| 16271 | a new tablespace. */ | ||
| 16272 | |||
| 16273 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 876 times.
|
893 | if (dict_table->ibd_file_missing) { |
| 16274 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_WARN, |
| 16275 | ER_TABLESPACE_MISSING, dict_table->name.m_name); | ||
| 16276 | } | ||
| 16277 | |||
| 16278 | 891 | err = row_discard_tablespace_for_mysql(dict_table->name.m_name, | |
| 16279 |
1/2✓ Branch 0 taken 891 times.
✗ Branch 1 not taken.
|
893 | m_prebuilt->trx); |
| 16280 | |||
| 16281 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 812 times.
|
817 | } else if (!dict_table->ibd_file_missing) { |
| 16282 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
10 | ib::error(ER_IB_MSG_567) |
| 16283 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | << "Unable to import tablespace " << dict_table->name |
| 16284 | << " because it already" | ||
| 16285 | " exists. Please DISCARD the tablespace" | ||
| 16286 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | " before IMPORT."; |
| 16287 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | ib_senderrf(m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, |
| 16288 | ER_TABLESPACE_EXISTS, dict_table->name.m_name); | ||
| 16289 | |||
| 16290 | 5 | return HA_ERR_TABLE_EXIST; | |
| 16291 | } else { | ||
| 16292 |
1/2✓ Branch 0 taken 788 times.
✗ Branch 1 not taken.
|
812 | err = row_import_for_mysql(dict_table, table_def, m_prebuilt); |
| 16293 | |||
| 16294 |
2/2✓ Branch 0 taken 572 times.
✓ Branch 1 taken 216 times.
|
788 | if (err == DB_SUCCESS) { |
| 16295 |
1/2✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
|
572 | info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE | |
| 16296 | HA_STATUS_AUTO); | ||
| 16297 | } | ||
| 16298 | } | ||
| 16299 | |||
| 16300 | /* Set the TABLESPACE DISCARD flag in the table definition | ||
| 16301 | on disk. */ | ||
| 16302 |
2/2✓ Branch 0 taken 1460 times.
✓ Branch 1 taken 219 times.
|
1679 | if (err == DB_SUCCESS) { |
| 16303 |
1/2✓ Branch 0 taken 1460 times.
✗ Branch 1 not taken.
|
1460 | dd_table_discard_tablespace(m_prebuilt->trx->mysql_thd, dict_table, |
| 16304 | table_def, discard); | ||
| 16305 | } | ||
| 16306 | |||
| 16307 |
6/6✓ Branch 0 taken 1460 times.
✓ Branch 1 taken 219 times.
✓ Branch 2 taken 572 times.
✓ Branch 3 taken 888 times.
✓ Branch 4 taken 571 times.
✓ Branch 5 taken 1108 times.
|
2251 | if (err == DB_SUCCESS && !discard && |
| 16308 |
3/4✓ Branch 0 taken 572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 571 times.
✓ Branch 3 taken 1 times.
|
572 | dict_stats_is_persistent_enabled(dict_table)) { |
| 16309 | dberr_t ret; | ||
| 16310 | |||
| 16311 | /* Adjust the persistent statistics. */ | ||
| 16312 |
1/2✓ Branch 0 taken 571 times.
✗ Branch 1 not taken.
|
571 | ret = dict_stats_update(dict_table, DICT_STATS_RECALC_PERSISTENT); |
| 16313 | |||
| 16314 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 571 times.
|
571 | if (ret != DB_SUCCESS) { |
| 16315 | ✗ | push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_ALTER_INFO, | |
| 16316 | "Error updating stats for table '%s'" | ||
| 16317 | " after table rebuild: %s", | ||
| 16318 | dict_table->name.m_name, ut_strerr(ret)); | ||
| 16319 | } | ||
| 16320 | } | ||
| 16321 | |||
| 16322 |
1/2✓ Branch 0 taken 1679 times.
✗ Branch 1 not taken.
|
1679 | return convert_error_code_to_mysql(err, dict_table->flags, nullptr); |
| 16323 | 1695 | } | |
| 16324 | |||
| 16325 | 50115 | int ha_innobase::truncate_impl(const char *name, TABLE *form, | |
| 16326 | dd::Table *table_def) { | ||
| 16327 |
1/2✓ Branch 0 taken 50115 times.
✗ Branch 1 not taken.
|
50115 | DBUG_TRACE; |
| 16328 | |||
| 16329 | /* Truncate of intrinsic table or hard-coded DD tables is not allowed | ||
| 16330 | for now. */ | ||
| 16331 |
2/4✓ Branch 0 taken 50115 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50115 times.
|
100230 | if (table_def == nullptr || |
| 16332 |
3/6✓ Branch 0 taken 50115 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50115 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 50115 times.
|
50115 | dict_sys_t::is_dd_table_id(table_def->se_private_id())) { |
| 16333 | ✗ | my_error(ER_NOT_ALLOWED_COMMAND, MYF(0)); | |
| 16334 | ✗ | return HA_ERR_UNSUPPORTED; | |
| 16335 | } | ||
| 16336 | |||
| 16337 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 50111 times.
|
50115 | if (high_level_read_only) { |
| 16338 | 4 | return HA_ERR_TABLE_READONLY; | |
| 16339 | } | ||
| 16340 | |||
| 16341 | char norm_name[FN_REFLEN]; | ||
| 16342 |
1/2✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
|
50111 | THD *thd = ha_thd(); |
| 16343 | 50111 | dict_table_t *innodb_table = nullptr; | |
| 16344 | 50111 | bool has_autoinc = false; | |
| 16345 | 50111 | int error = 0; | |
| 16346 |
1/2✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
|
50111 | const bool is_instant = dd_table_has_instant_cols(*table_def); |
| 16347 | |||
| 16348 |
2/4✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50111 times.
|
50111 | if (!normalize_table_name(norm_name, name)) { |
| 16349 | /* purecov: begin inspected */ | ||
| 16350 | ✗ | ut_d(ut_error); | |
| 16351 | ut_o(return (HA_ERR_TOO_LONG_PATH)); | ||
| 16352 | /* purecov: end */ | ||
| 16353 | } | ||
| 16354 | |||
| 16355 | innobase_truncate<dd::Table> truncator(thd, norm_name, form, table_def, false, | ||
| 16356 |
1/2✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
|
50111 | true); |
| 16357 | |||
| 16358 |
1/2✓ Branch 0 taken 50111 times.
✗ Branch 1 not taken.
|
50111 | error = truncator.open_table(innodb_table); |
| 16359 | |||
| 16360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50111 times.
|
50111 | if (error != 0) { |
| 16361 | ✗ | return error; | |
| 16362 | } | ||
| 16363 | |||
| 16364 | 50111 | has_autoinc = dict_table_has_autoinc_col(innodb_table); | |
| 16365 | |||
| 16366 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50109 times.
|
50111 | if (dict_table_is_discarded(innodb_table)) { |
| 16367 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, norm_name); |
| 16368 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 16369 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50107 times.
|
50109 | } else if (innodb_table->ibd_file_missing) { |
| 16370 | 2 | return innodb_table->keyring_encryption_info.page0_has_crypt_data == true | |
| 16371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | ? HA_ERR_ENCRYPTION_KEY_MISSING |
| 16372 | 2 | : HA_ERR_TABLESPACE_MISSING; | |
| 16373 | } | ||
| 16374 | |||
| 16375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50107 times.
|
50107 | if (UNIV_UNLIKELY(innodb_table->is_corrupt)) return HA_ERR_CRASHED; |
| 16376 | |||
| 16377 |
1/2✓ Branch 0 taken 50107 times.
✗ Branch 1 not taken.
|
50107 | trx_t *trx = check_trx_exists(thd); |
| 16378 |
1/2✓ Branch 0 taken 50107 times.
✗ Branch 1 not taken.
|
50107 | innobase_register_trx(ht, thd, trx); |
| 16379 | |||
| 16380 |
1/2✓ Branch 0 taken 50091 times.
✗ Branch 1 not taken.
|
50107 | error = truncator.exec(); |
| 16381 | |||
| 16382 |
2/2✓ Branch 0 taken 50086 times.
✓ Branch 1 taken 5 times.
|
50091 | if (error == 0) { |
| 16383 |
2/2✓ Branch 0 taken 369 times.
✓ Branch 1 taken 49717 times.
|
50086 | if (has_autoinc) { |
| 16384 |
2/4✓ Branch 0 taken 369 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 369 times.
✗ Branch 3 not taken.
|
369 | dd_set_autoinc(table_def->se_private_data(), 0); |
| 16385 | } | ||
| 16386 | |||
| 16387 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 50078 times.
|
50086 | if (is_instant) { |
| 16388 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (dd_clear_instant_table(*table_def, true) != DB_SUCCESS) { |
| 16389 | ✗ | error = HA_ERR_GENERIC; | |
| 16390 | } | ||
| 16391 | } | ||
| 16392 | } | ||
| 16393 | |||
| 16394 | 50091 | return error; | |
| 16395 | 50099 | } | |
| 16396 | |||
| 16397 | /** Drop a table. | ||
| 16398 | @param[in] name table name | ||
| 16399 | @param[in] table_def dd::Table describing table to | ||
| 16400 | be dropped | ||
| 16401 | @return error number | ||
| 16402 | @retval 0 on success */ | ||
| 16403 | 328139 | int ha_innobase::delete_table(const char *name, const dd::Table *table_def) { | |
| 16404 |
4/4✓ Branch 0 taken 145496 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 328137 times.
|
473635 | if (table_def != nullptr && |
| 16405 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 145494 times.
|
145496 | dict_sys_t::is_dd_table_id(table_def->se_private_id())) { |
| 16406 | 2 | my_error(ER_NOT_ALLOWED_COMMAND, MYF(0)); | |
| 16407 | 2 | return (HA_ERR_UNSUPPORTED); | |
| 16408 | } | ||
| 16409 | |||
| 16410 | 328137 | THD *thd = ha_thd(); | |
| 16411 | 328137 | trx_t *trx = check_trx_exists(thd); | |
| 16412 | |||
| 16413 |
6/6✓ Branch 0 taken 145494 times.
✓ Branch 1 taken 182643 times.
✓ Branch 2 taken 99389 times.
✓ Branch 3 taken 46105 times.
✓ Branch 4 taken 99389 times.
✓ Branch 5 taken 228748 times.
|
328137 | if (table_def != nullptr && table_def->is_persistent()) { |
| 16414 | 99389 | innobase_register_trx(ht, thd, trx); | |
| 16415 | } | ||
| 16416 | |||
| 16417 | 328137 | return (innobase_basic_ddl::delete_impl(thd, name, table_def, nullptr)); | |
| 16418 | } | ||
| 16419 | |||
| 16420 | /** Validate the parameters in st_alter_tablespace | ||
| 16421 | before using them in InnoDB tablespace functions. | ||
| 16422 | @param[in] type Type os tablespace being validated | ||
| 16423 | @param[in] alter_info How to do the command. | ||
| 16424 | @return MySQL handler error code like HA_... */ | ||
| 16425 | 1350 | static int validate_create_tablespace_info(ib_file_suffix type, | |
| 16426 | st_alter_tablespace *alter_info) { | ||
| 16427 | /* The parser ensures that these fields are provided. */ | ||
| 16428 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
|
1350 | ut_a(alter_info->data_file_name != nullptr); |
| 16429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
|
1350 | ut_a(alter_info->tablespace_name != nullptr); |
| 16430 | |||
| 16431 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
|
1350 | if (high_level_read_only) { |
| 16432 | ✗ | return (HA_ERR_INNODB_READ_ONLY); | |
| 16433 | } | ||
| 16434 | |||
| 16435 | /* Name validation should be ensured from the SQL layer. */ | ||
| 16436 |
2/4✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1350 times.
|
1350 | ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type, |
| 16437 | alter_info->tablespace_name)); | ||
| 16438 | |||
| 16439 | 1350 | int error = 0; | |
| 16440 | |||
| 16441 | /* Make sure the tablespace is not already open. */ | ||
| 16442 | |||
| 16443 | space_id_t space_id; | ||
| 16444 | |||
| 16445 |
1/2✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
|
1350 | space_id = fil_space_get_id_by_name(alter_info->tablespace_name); |
| 16446 | |||
| 16447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
|
1350 | if (space_id != SPACE_UNKNOWN) { |
| 16448 | ✗ | my_printf_error(ER_TABLESPACE_EXISTS, | |
| 16449 | "InnoDB: A tablespace named `%s`" | ||
| 16450 | " already exists.", | ||
| 16451 | MYF(0), alter_info->tablespace_name); | ||
| 16452 | ✗ | error = HA_ERR_TABLESPACE_EXISTS; | |
| 16453 | } | ||
| 16454 | |||
| 16455 |
4/4✓ Branch 0 taken 974 times.
✓ Branch 1 taken 376 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 919 times.
|
1350 | if (type == IBD && alter_info->file_block_size) { |
| 16456 | /* Check for a bad file block size. */ | ||
| 16457 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2 times.
|
55 | if (!ut_is_2pow(alter_info->file_block_size) || |
| 16458 |
1/2✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
|
53 | alter_info->file_block_size < UNIV_ZIP_SIZE_MIN || |
| 16459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | alter_info->file_block_size > UNIV_PAGE_SIZE_MAX) { |
| 16460 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 16461 | "InnoDB does not support" | ||
| 16462 | " FILE_BLOCK_SIZE=%llu", | ||
| 16463 | MYF(0), alter_info->file_block_size); | ||
| 16464 | 2 | error = HA_WRONG_CREATE_OPTION; | |
| 16465 | |||
| 16466 | /* Don't allow a file block size larger than UNIV_PAGE_SIZE. */ | ||
| 16467 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 41 times.
|
53 | } else if (alter_info->file_block_size > UNIV_PAGE_SIZE) { |
| 16468 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 16469 | "InnoDB: Cannot create a tablespace" | ||
| 16470 | " with FILE_BLOCK_SIZE=%llu because" | ||
| 16471 | " INNODB_PAGE_SIZE=%lu.", | ||
| 16472 | MYF(0), alter_info->file_block_size, UNIV_PAGE_SIZE); | ||
| 16473 | 12 | error = HA_WRONG_CREATE_OPTION; | |
| 16474 | |||
| 16475 | /* Don't allow a compressed tablespace when page size > 16k. */ | ||
| 16476 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 28 times.
|
41 | } else if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF && |
| 16477 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
|
13 | alter_info->file_block_size != UNIV_PAGE_SIZE) { |
| 16478 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, |
| 16479 | "InnoDB: Cannot create a COMPRESSED" | ||
| 16480 | " tablespace when innodb_page_size >" | ||
| 16481 | " 16k.", | ||
| 16482 | MYF(0)); | ||
| 16483 | 11 | error = HA_WRONG_CREATE_OPTION; | |
| 16484 | } | ||
| 16485 | } | ||
| 16486 | |||
| 16487 | /* Validate AUTOEXTEND_SIZE clause. */ | ||
| 16488 | 1350 | if (alter_info->autoextend_size.has_value() && | |
| 16489 |
6/8✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1311 times.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 1346 times.
|
1389 | alter_info->autoextend_size.value() > 0 && |
| 16490 |
4/6✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 35 times.
|
39 | validate_autoextend_size_value(alter_info->autoextend_size.value()) != |
| 16491 | DB_SUCCESS) { | ||
| 16492 | 4 | error = HA_WRONG_CREATE_OPTION; | |
| 16493 | } | ||
| 16494 | |||
| 16495 | /* Validate the ADD DATAFILE name. */ | ||
| 16496 |
1/2✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
|
1350 | std::string datafile_name(alter_info->data_file_name); |
| 16497 | |||
| 16498 | /* Undo Tablespace ADD DATAFILE filenames cannot be relative paths | ||
| 16499 | because it would be unclear what they are relative to. However, | ||
| 16500 | srv_undo_dir can be a relative directory. So evaluate this | ||
| 16501 | ADD DATAFILE value before it is appended to the undo dir. */ | ||
| 16502 |
7/8✓ Branch 0 taken 376 times.
✓ Branch 1 taken 974 times.
✓ Branch 2 taken 376 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 369 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1343 times.
|
1350 | if (type == IBU && Fil_path::is_relative_path(datafile_name)) { |
| 16503 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error(ER_WRONG_FILE_NAME, |
| 16504 | "The ADD DATAFILE filepath for an UNDO TABLESPACE" | ||
| 16505 | " cannot be a relative path.", | ||
| 16506 | MYF(0)); | ||
| 16507 | |||
| 16508 | 7 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16509 | } | ||
| 16510 | |||
| 16511 | /* If this is an undo tablespace basename and the innodb-undo-directory | ||
| 16512 | is not the datadir, then use an undo::Tablespace object to get the name | ||
| 16513 | since it will to attach a basename to the undo directory instead of the | ||
| 16514 | datadir. */ | ||
| 16515 |
2/2✓ Branch 0 taken 358 times.
✓ Branch 1 taken 18 times.
|
376 | if (alter_info->ts_cmd_type == CREATE_UNDO_TABLESPACE && |
| 16516 |
4/4✓ Branch 0 taken 376 times.
✓ Branch 1 taken 974 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1348 times.
|
1726 | std::string::npos == datafile_name.find_first_of(Fil_path::SEPARATOR) && |
| 16517 |
3/4✓ Branch 0 taken 358 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 356 times.
|
358 | !MySQL_undo_path.is_same_as(MySQL_datadir_path)) { |
| 16518 | 2 | undo::Tablespace undo_space(0); | |
| 16519 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | undo_space.set_file_name(datafile_name.c_str()); |
| 16520 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | datafile_name = undo_space.file_name(); |
| 16521 | 2 | } | |
| 16522 | |||
| 16523 |
1/2✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
|
1350 | Fil_path filepath(datafile_name, true); |
| 16524 | |||
| 16525 | /* If this path contains a circular section such as "/anydir/../" then | ||
| 16526 | reject it since if that unnecessary directory reference is deleted | ||
| 16527 | the path will not be useaable on Linux. */ | ||
| 16528 |
3/4✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1341 times.
|
1350 | if (filepath.is_circular()) { |
| 16529 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | my_printf_error(ER_WRONG_FILE_NAME, |
| 16530 | "The ADD DATAFILE filepath cannot contain circular " | ||
| 16531 | "directory references.", | ||
| 16532 | MYF(0)); | ||
| 16533 | 9 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16534 | } | ||
| 16535 | |||
| 16536 | #ifndef _WIN32 | ||
| 16537 | /* On Non-Windows platforms, '\\' is a valid file name character. | ||
| 16538 | But for InnoDB datafiles, we always assume it is a directory | ||
| 16539 | separator and convert these to '/' */ | ||
| 16540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1350 times.
|
1350 | if (strchr(filepath, '\\') != nullptr) { |
| 16541 | ✗ | ib::warn(ER_IB_MSG_568) << "Converting backslash to forward slash in" | |
| 16542 | ✗ | " ADD DATAFILE " | |
| 16543 | ✗ | << filepath.path(); | |
| 16544 | } | ||
| 16545 | #endif /* _WIN32 */ | ||
| 16546 | |||
| 16547 | /* The filepath must end with a valid suffix and contain a basename of at | ||
| 16548 | least 1 character before the suffix. */ | ||
| 16549 |
1/2✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
|
1350 | size_t dirname_len = dirname_length(filepath); |
| 16550 | 1350 | const char *basename = filepath + dirname_len; | |
| 16551 | 1350 | auto basename_len = strlen(basename); | |
| 16552 | |||
| 16553 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1343 times.
|
1350 | if (basename_len <= 4) { |
| 16554 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error( |
| 16555 | ER_WRONG_FILE_NAME, | ||
| 16556 | "The ADD DATAFILE filepath does not have a proper filename.", MYF(0)); | ||
| 16557 | 7 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16558 | } | ||
| 16559 | |||
| 16560 |
4/6✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1350 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1344 times.
|
1350 | if (!Fil_path::has_suffix(type, basename)) { |
| 16561 | 6 | my_printf_error(ER_WRONG_FILE_NAME, | |
| 16562 | "The ADD DATAFILE filepath must end with '%s'.", MYF(0), | ||
| 16563 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | dot_ext[type]); |
| 16564 | 6 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16565 | } | ||
| 16566 | |||
| 16567 |
3/4✓ Branch 0 taken 1350 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1348 times.
|
1350 | if (!filepath.is_valid()) { |
| 16568 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_WRONG_FILE_NAME, MYF(0), filepath.path().c_str()); |
| 16569 | |||
| 16570 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_WRONG_FILE_NAME, "Invalid use of ':'.", MYF(0)); |
| 16571 | |||
| 16572 | 2 | return (HA_ERR_WRONG_FILE_NAME); | |
| 16573 | } | ||
| 16574 | |||
| 16575 | /* If this file already exists, we cannot use this filename. */ | ||
| 16576 |
3/4✓ Branch 0 taken 1348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1344 times.
|
1348 | if (os_file_exists(filepath.path().c_str())) { |
| 16577 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | my_printf_error(ER_WRONG_FILE_NAME, |
| 16578 | "The ADD DATAFILE filepath already exists.", MYF(0)); | ||
| 16579 | 4 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16580 | } | ||
| 16581 | |||
| 16582 | 78 | Fil_path dirpath((dirname_len == 0 ? "." : datafile_name.c_str()), | |
| 16583 |
5/6✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1270 times.
✓ Branch 2 taken 78 times.
✓ Branch 3 taken 1270 times.
✓ Branch 4 taken 1348 times.
✗ Branch 5 not taken.
|
1426 | (dirname_len == 0 ? 1 : dirname_len), true); |
| 16584 | |||
| 16585 |
3/4✓ Branch 0 taken 1348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1342 times.
|
1348 | if (!dirpath.is_directory_and_exists()) { |
| 16586 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | ib::error(ER_IB_MSG_WRONG_TABLESPACE_DIR, alter_info->tablespace_name); |
| 16587 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | my_printf_error(ER_WRONG_FILE_NAME, |
| 16588 | "The directory does not exist or is incorrect.", MYF(0)); | ||
| 16589 | |||
| 16590 | 6 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16591 | } | ||
| 16592 | |||
| 16593 | /* Do not allow the file to be created in a unique undo directory. */ | ||
| 16594 |
6/6✓ Branch 0 taken 972 times.
✓ Branch 1 taken 376 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 966 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1347 times.
|
1354 | if (type == IBD && MySQL_undo_path_is_unique && |
| 16595 |
3/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
|
6 | (MySQL_undo_path.is_same_as(dirpath) || |
| 16596 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
|
5 | MySQL_undo_path.is_ancestor(dirpath))) { |
| 16597 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | std::string msg("The DATAFILE location cannot be the undo directory."); |
| 16598 | |||
| 16599 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); |
| 16600 | |||
| 16601 | 1 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE, | |
| 16602 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | alter_info->tablespace_name, msg.c_str()); |
| 16603 | |||
| 16604 | 1 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16605 | 1 | } | |
| 16606 | |||
| 16607 | /* General tablespaces can be inside but not under the datadir | ||
| 16608 | since those directories contain datafiles for specific schemas.*/ | ||
| 16609 |
7/8✓ Branch 0 taken 972 times.
✓ Branch 1 taken 376 times.
✓ Branch 2 taken 972 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 965 times.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 1341 times.
|
1348 | if (type == IBD && MySQL_datadir_path.is_ancestor(dirpath)) { |
| 16610 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | std::string msg("The DATAFILE location cannot be under the datadir."); |
| 16611 | |||
| 16612 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); |
| 16613 | |||
| 16614 | 7 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE, | |
| 16615 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | alter_info->tablespace_name, msg.c_str()); |
| 16616 | |||
| 16617 | 7 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16618 | 7 | } | |
| 16619 | |||
| 16620 | /* Validate the tablespace location. */ | ||
| 16621 |
3/4✓ Branch 0 taken 1348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1341 times.
✓ Branch 3 taken 7 times.
|
2689 | bool in_datadir = MySQL_datadir_path.is_ancestor(dirpath) || |
| 16622 |
3/4✓ Branch 0 taken 1341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1291 times.
✓ Branch 3 taken 50 times.
|
1341 | MySQL_datadir_path.is_same_as(dirpath); |
| 16623 | bool in_known_location = | ||
| 16624 |
3/4✓ Branch 0 taken 1298 times.
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
1348 | in_datadir ? true : fil_path_is_known(dirpath.path()); |
| 16625 | |||
| 16626 | /* All undo and general tablespaces must be in known directories */ | ||
| 16627 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1328 times.
|
1348 | if (!in_known_location) { |
| 16628 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | std::string msg("The "); |
| 16629 |
3/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | msg += (type == IBU ? "UNDO " : ""); |
| 16630 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | msg += "DATAFILE location must be in a known directory."; |
| 16631 | |||
| 16632 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | my_printf_error(ER_WRONG_FILE_NAME, "%s", MYF(0), msg.c_str()); |
| 16633 | |||
| 16634 | 20 | ib::error(ER_IB_MSG_INVALID_LOCATION_FOR_TABLESPACE, | |
| 16635 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | alter_info->tablespace_name, msg.c_str()); |
| 16636 | |||
| 16637 | 20 | error = HA_ERR_WRONG_FILE_NAME; | |
| 16638 | 20 | } | |
| 16639 | |||
| 16640 | 1348 | return (error); | |
| 16641 | 1350 | } | |
| 16642 | |||
| 16643 | /** CREATE a tablespace. | ||
| 16644 | @param[in] hton Handlerton of InnoDB | ||
| 16645 | @param[in] thd Connection | ||
| 16646 | @param[in] alter_info How to do the command | ||
| 16647 | @param[in,out] dd_space Tablespace metadata | ||
| 16648 | @return MySQL error code*/ | ||
| 16649 | 974 | static int innodb_create_tablespace(handlerton *hton, THD *thd, | |
| 16650 | st_alter_tablespace *alter_info, | ||
| 16651 | dd::Tablespace *dd_space) { | ||
| 16652 | int error; | ||
| 16653 |
1/2✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
|
974 | Tablespace tablespace; |
| 16654 | 974 | uint32_t fsp_flags = 0; | |
| 16655 | 974 | fil_encryption_t keyring_encryption_mode{FIL_ENCRYPTION_DEFAULT}; | |
| 16656 | |||
| 16657 |
1/2✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
|
974 | DBUG_TRACE; |
| 16658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 974 times.
|
974 | assert(hton == innodb_hton_ptr); |
| 16659 | |||
| 16660 |
2/4✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 974 times.
|
974 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 16661 |
2/4✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 974 times.
|
974 | ut_ad(strcmp(alter_info->data_file_name, |
| 16662 | dd_tablespace_get_filename(dd_space)) == 0); | ||
| 16663 | |||
| 16664 | /* Be sure the input parameters are valid before continuing. */ | ||
| 16665 |
1/2✓ Branch 0 taken 974 times.
✗ Branch 1 not taken.
|
974 | error = validate_create_tablespace_info(IBD, alter_info); |
| 16666 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 912 times.
|
974 | if (error) { |
| 16667 | 62 | return error; | |
| 16668 | } | ||
| 16669 | |||
| 16670 | /* Create the tablespace object. */ | ||
| 16671 |
1/2✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
|
912 | tablespace.set_name(alter_info->tablespace_name); |
| 16672 | |||
| 16673 |
1/2✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
|
912 | dberr_t err = tablespace.add_datafile(alter_info->data_file_name); |
| 16674 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 912 times.
|
912 | if (err != DB_SUCCESS) { |
| 16675 | ✗ | return convert_error_code_to_mysql(err, 0, nullptr); | |
| 16676 | } | ||
| 16677 | |||
| 16678 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 877 times.
|
947 | tablespace.set_autoextend_size(alter_info->autoextend_size.has_value() |
| 16679 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35 | ? alter_info->autoextend_size.value() |
| 16680 | : 0); | ||
| 16681 | |||
| 16682 | /* Get the transaction associated with the current thd. */ | ||
| 16683 |
1/2✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
|
912 | trx_t *trx = check_trx_exists(thd); |
| 16684 |
1/2✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
|
912 | TrxInInnoDB trx_in_innodb(trx); |
| 16685 |
1/2✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
|
912 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 16686 | 912 | ++trx->will_lock; | |
| 16687 | |||
| 16688 |
1/2✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
|
912 | row_mysql_lock_data_dictionary(trx, UT_LOCATION_HERE); |
| 16689 | |||
| 16690 | /* In FSP_FLAGS, a zip_ssize of zero means that the tablespace | ||
| 16691 | holds non-compresssed tables. A non-zero zip_ssize means that | ||
| 16692 | the general tablespace can ONLY contain compressed tables. */ | ||
| 16693 | 912 | uint32_t zip_size = static_cast<uint32_t>(alter_info->file_block_size); | |
| 16694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 912 times.
|
912 | ut_ad(zip_size <= UNIV_PAGE_SIZE_MAX); |
| 16695 |
2/2✓ Branch 0 taken 882 times.
✓ Branch 1 taken 30 times.
|
912 | if (zip_size == 0) { |
| 16696 | 882 | zip_size = UNIV_PAGE_SIZE; | |
| 16697 | } | ||
| 16698 | 912 | bool zipped = (zip_size != UNIV_PAGE_SIZE); | |
| 16699 |
1/2✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
|
912 | page_size_t page_size(zip_size, UNIV_PAGE_SIZE, zipped); |
| 16700 | 912 | bool atomic_blobs = page_size.is_compressed(); | |
| 16701 | 912 | KeyringEncryptionKeyIdInfo keyring_encryption_key_id; | |
| 16702 | 912 | bool encrypted = false; | |
| 16703 | 912 | dd::String_type encrypt; | |
| 16704 |
4/8✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 912 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 912 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 912 times.
✗ Branch 7 not taken.
|
912 | if (dd_space->options().exists("encryption")) { |
| 16705 |
3/6✓ Branch 0 taken 912 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 912 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 912 times.
✗ Branch 5 not taken.
|
912 | (void)dd_space->options().get("encryption", &encrypt); |
| 16706 | |||
| 16707 | /* Validate Encryption option provided */ | ||
| 16708 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 892 times.
|
912 | if (Encryption::validate_for_tablespace(encrypt.c_str()) != DB_SUCCESS) { |
| 16709 | /* Incorrect encryption option */ | ||
| 16710 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); |
| 16711 | 20 | err = DB_UNSUPPORTED; | |
| 16712 | 22 | goto error_exit; | |
| 16713 | } | ||
| 16714 | |||
| 16715 | 892 | bool explicit_encryption{false}; | |
| 16716 |
4/8✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 892 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 892 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 892 times.
✗ Branch 7 not taken.
|
892 | if (dd_space->options().exists("explicit_encryption")) { |
| 16717 |
3/6✓ Branch 0 taken 892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 892 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 892 times.
✗ Branch 5 not taken.
|
892 | (void)dd_space->options().get("explicit_encryption", |
| 16718 | &explicit_encryption); | ||
| 16719 | } | ||
| 16720 | /* Validate that encryption is not MK encryption if online encryption is ON. | ||
| 16721 | encrypt_type is set to Y for both MK encryption and ONLINE_TO_KEYRING | ||
| 16722 | encryption. However, when d_t_e=ONLINE_TO_KEYRING is set it is only | ||
| 16723 | possible to specify MK encryption by explicitly specifying | ||
| 16724 | ENCRYPTION='Y'. We use this information here. | ||
| 16725 | */ | ||
| 16726 |
2/2✓ Branch 0 taken 272 times.
✓ Branch 1 taken 24 times.
|
1188 | if (Encryption::is_master_key_encryption(encrypt.c_str()) && |
| 16727 |
4/6✓ Branch 0 taken 296 times.
✓ Branch 1 taken 596 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 272 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 892 times.
|
1188 | explicit_encryption && Encryption::is_online_encryption_on()) { |
| 16728 | ✗ | my_printf_error( | |
| 16729 | ER_KEYRING_ILLEGAL_ENCRYPTION_OPTION, | ||
| 16730 | "InnoDB: ENCRYPTED='Y' not supported for tablespace because " | ||
| 16731 | "online encryption to KEYRING is turned ON.", | ||
| 16732 | MYF(0)); | ||
| 16733 | ✗ | err = DB_UNSUPPORTED; | |
| 16734 | ✗ | goto error_exit; | |
| 16735 | } | ||
| 16736 | |||
| 16737 | /* If encryption is to be done */ | ||
| 16738 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 596 times.
|
892 | if (!Encryption::is_none(encrypt.c_str())) { |
| 16739 | /* Check if keyring is ready. */ | ||
| 16740 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 294 times.
|
296 | if (!Encryption::check_keyring()) { |
| 16741 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 16742 | 2 | err = DB_UNSUPPORTED; | |
| 16743 | 2 | goto error_exit; | |
| 16744 | } | ||
| 16745 | 294 | encrypted = true; | |
| 16746 | } | ||
| 16747 | |||
| 16748 |
4/6✓ Branch 0 taken 890 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 888 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
890 | DBUG_EXECUTE_IF("ib_crash_during_create_tablespace_for_encryption", |
| 16749 | DBUG_SUICIDE();); | ||
| 16750 | } | ||
| 16751 | |||
| 16752 | /* Create the filespace flags */ | ||
| 16753 | 888 | fsp_flags = | |
| 16754 |
1/2✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
|
888 | fsp_flags_init(page_size, /* page sizes and a flag if compressed */ |
| 16755 | atomic_blobs, /* needed only for compressed tables */ | ||
| 16756 | false, /* This is not a file-per-table tablespace */ | ||
| 16757 | true, /* This is a general shared tablespace */ | ||
| 16758 | false, /* Temporary General Tablespaces not allowed */ | ||
| 16759 | encrypted); /* If tablespace is to be Encrypted */ | ||
| 16760 |
1/2✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
|
888 | tablespace.set_flags(fsp_flags); |
| 16761 | |||
| 16762 | 1776 | keyring_encryption_key_id = { | |
| 16763 | 888 | alter_info->encryption_key_id.was_encryption_key_id_set, | |
| 16764 | alter_info->encryption_key_id.id}; | ||
| 16765 | |||
| 16766 | keyring_encryption_mode = | ||
| 16767 |
1/2✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
|
888 | get_encryption_mode(encrypt.c_str(), alter_info->explicit_encryption); |
| 16768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
|
888 | ut_ad(keyring_encryption_mode != FIL_ENCRYPTION_ON); |
| 16769 | |||
| 16770 |
1/2✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
|
888 | err = dict_build_tablespace(trx, &tablespace, keyring_encryption_mode, |
| 16771 | keyring_encryption_key_id); | ||
| 16772 | |||
| 16773 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 885 times.
|
888 | if (err == DB_SUCCESS) { |
| 16774 | /* Update the fil_space_t with autoextend_size value. */ | ||
| 16775 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | fil_set_autoextend_size(tablespace.space_id(), |
| 16776 | tablespace.get_autoextend_size()); | ||
| 16777 | |||
| 16778 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | err = btr_sdi_create_index(tablespace.space_id(), true); |
| 16779 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | if (err == DB_SUCCESS) { |
| 16780 | 885 | fsp_flags_set_sdi(fsp_flags); | |
| 16781 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | tablespace.set_flags(fsp_flags); |
| 16782 | |||
| 16783 | /* Make sure the DD has the space_id and the flags. */ | ||
| 16784 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | dd_write_tablespace(dd_space, tablespace.space_id(), tablespace.flags(), |
| 16785 | DD_SPACE_STATE_NORMAL); | ||
| 16786 | } | ||
| 16787 | } | ||
| 16788 | |||
| 16789 | 3 | error_exit: | |
| 16790 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 885 times.
|
910 | if (err != DB_SUCCESS) { |
| 16791 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 16792 | } | ||
| 16793 | |||
| 16794 |
1/2✓ Branch 0 taken 910 times.
✗ Branch 1 not taken.
|
910 | row_mysql_unlock_data_dictionary(trx); |
| 16795 | |||
| 16796 | 910 | return error; | |
| 16797 | 972 | } | |
| 16798 | |||
| 16799 | /** Alter AUTOEXTEND_SIZE a tablespace. | ||
| 16800 | @param[in] hton Handlerton of InnoDB | ||
| 16801 | @param[in] alter_info How to do the command | ||
| 16802 | @param[in] old_dd_space Tablespace metadata | ||
| 16803 | @return MySQL error code */ | ||
| 16804 | 5015 | static int innobase_alter_autoextend_size_tablespace( | |
| 16805 | handlerton *hton, st_alter_tablespace *alter_info, | ||
| 16806 | const dd::Tablespace *old_dd_space) { | ||
| 16807 | 5015 | space_id_t space_id = SPACE_UNKNOWN; | |
| 16808 | |||
| 16809 |
1/2✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
|
5015 | DBUG_TRACE; |
| 16810 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
|
5015 | assert(hton == innodb_hton_ptr); |
| 16811 | |||
| 16812 |
3/6✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5015 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5015 times.
✗ Branch 5 not taken.
|
5015 | DEBUG_SYNC(current_thd, "innodb_alter_autoextend_size_tablespace"); |
| 16813 | |||
| 16814 |
2/4✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
|
5015 | ut_ad(alter_info->tablespace_name == old_dd_space->name()); |
| 16815 | |||
| 16816 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
|
5015 | if (srv_read_only_mode) { |
| 16817 | ✗ | return HA_ERR_INNODB_READ_ONLY; | |
| 16818 | } | ||
| 16819 | |||
| 16820 | /* Validate the name */ | ||
| 16821 |
2/4✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
|
5015 | ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type, |
| 16822 | alter_info->tablespace_name)); | ||
| 16823 | |||
| 16824 | /* Be sure that this tablespace is known and valid. */ | ||
| 16825 |
2/6✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
10030 | if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 16826 |
4/8✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5015 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5015 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5015 times.
✗ Branch 7 not taken.
|
15045 | &space_id) || |
| 16827 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
|
5015 | space_id == SPACE_UNKNOWN) { |
| 16828 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 16829 | } | ||
| 16830 | |||
| 16831 | /* Make sure tablespace is loaded. */ | ||
| 16832 |
1/2✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
|
5015 | fil_space_t *space = fil_space_acquire(space_id); |
| 16833 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
|
5015 | if (space == nullptr) { |
| 16834 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 16835 | } | ||
| 16836 |
2/4✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5015 times.
|
5015 | ut_ad(fsp_flags_is_valid(space->flags)); |
| 16837 | |||
| 16838 | /* Validate the autoextend_size value. */ | ||
| 16839 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5015 times.
|
5015 | ut_ad(alter_info->autoextend_size.has_value()); |
| 16840 | |||
| 16841 |
1/2✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
|
5015 | uint64_t autoextend_size = alter_info->autoextend_size.value(); |
| 16842 | |||
| 16843 |
2/2✓ Branch 0 taken 5006 times.
✓ Branch 1 taken 9 times.
|
5015 | if (autoextend_size > 0) { |
| 16844 |
1/2✓ Branch 0 taken 5006 times.
✗ Branch 1 not taken.
|
5006 | int ret = validate_autoextend_size_value(autoextend_size); |
| 16845 | |||
| 16846 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5004 times.
|
5006 | if (ret != DB_SUCCESS) { |
| 16847 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | fil_space_release(space); |
| 16848 | 2 | return ret; | |
| 16849 | } | ||
| 16850 | } | ||
| 16851 | |||
| 16852 |
2/4✓ Branch 0 taken 5013 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5013 times.
✗ Branch 3 not taken.
|
5013 | fil_set_autoextend_size(space_id, alter_info->autoextend_size.value()); |
| 16853 | |||
| 16854 |
1/2✓ Branch 0 taken 5013 times.
✗ Branch 1 not taken.
|
5013 | fil_space_release(space); |
| 16855 | |||
| 16856 | 5013 | return 0; | |
| 16857 | 5015 | } | |
| 16858 | |||
| 16859 | /** | ||
| 16860 | Return data filename extension for a InnoDB tablespace. | ||
| 16861 | */ | ||
| 16862 | |||
| 16863 | 128 | static const char *innobase_get_tablespace_filename_ext() { return ".ibd"; } | |
| 16864 | |||
| 16865 | /** Alter Encrypt/Unencrypt a tablespace. | ||
| 16866 | @param[in] hton Handlerton of InnoDB | ||
| 16867 | @param[in] thd Connection | ||
| 16868 | @param[in] alter_info How to do the command | ||
| 16869 | @param[in] old_dd_space Tablespace metadata | ||
| 16870 | @param[in,out] new_dd_space Tablespace metadata | ||
| 16871 | @return MySQL error code*/ | ||
| 16872 | 495 | static int innobase_alter_encrypt_tablespace(handlerton *hton, THD *thd, | |
| 16873 | st_alter_tablespace *alter_info, | ||
| 16874 | const dd::Tablespace *old_dd_space, | ||
| 16875 | dd::Tablespace *new_dd_space) { | ||
| 16876 | 495 | trx_t *trx = nullptr; | |
| 16877 | 495 | dberr_t err = DB_SUCCESS; | |
| 16878 | 495 | int error = 0; | |
| 16879 | 495 | space_id_t space_id = SPACE_UNKNOWN; | |
| 16880 | |||
| 16881 |
1/2✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
|
495 | DBUG_TRACE; |
| 16882 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 495 times.
|
495 | assert(hton == innodb_hton_ptr); |
| 16883 | |||
| 16884 |
4/6✓ Branch 0 taken 469 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 469 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 469 times.
✗ Branch 5 not taken.
|
495 | DEBUG_SYNC(current_thd, "innodb_alter_encrypt_tablespace"); |
| 16885 | |||
| 16886 |
2/4✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 495 times.
|
495 | ut_ad(alter_info->tablespace_name == old_dd_space->name()); |
| 16887 | |||
| 16888 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 495 times.
|
495 | if (srv_read_only_mode) { |
| 16889 | ✗ | return HA_ERR_INNODB_READ_ONLY; | |
| 16890 | } | ||
| 16891 | |||
| 16892 | /* Name validation should be ensured from the SQL layer. */ | ||
| 16893 |
2/4✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 495 times.
|
495 | ut_ad(0 == validate_tablespace_name(alter_info->ts_cmd_type, |
| 16894 | alter_info->tablespace_name)); | ||
| 16895 | |||
| 16896 | /* Be sure that this tablespace is known and valid. */ | ||
| 16897 |
2/6✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 495 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
990 | if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 16898 |
4/8✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 495 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 495 times.
✗ Branch 7 not taken.
|
1485 | &space_id) || |
| 16899 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 495 times.
|
495 | space_id == SPACE_UNKNOWN) { |
| 16900 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 16901 | } | ||
| 16902 | |||
| 16903 | /* Make sure keyring plugin is loaded. */ | ||
| 16904 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 479 times.
|
495 | if (!Encryption::check_keyring()) { |
| 16905 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); |
| 16906 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr); |
| 16907 | 16 | return error; | |
| 16908 | } | ||
| 16909 | |||
| 16910 | /* Make sure tablespace is loaded. */ | ||
| 16911 |
1/2✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
|
479 | fil_space_t *space = fil_space_get(space_id); |
| 16912 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 479 times.
|
479 | if (space == nullptr) { |
| 16913 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 16914 | } | ||
| 16915 |
2/4✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 479 times.
|
479 | ut_ad(fsp_flags_is_valid(space->flags)); |
| 16916 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 479 times.
|
479 | ut_ad(FSP_FLAGS_GET_SHARED(space->flags)); |
| 16917 | |||
| 16918 |
1/2✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
|
479 | const dd::Properties &oldopts = old_dd_space->options(); |
| 16919 |
1/2✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
|
479 | const dd::Properties &newopts = new_dd_space->options(); |
| 16920 | |||
| 16921 | /* Get value of old encryption option. */ | ||
| 16922 | 479 | dd::String_type oldenc; | |
| 16923 |
3/6✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 479 times.
✗ Branch 5 not taken.
|
479 | if (oldopts.exists("encryption")) { |
| 16924 |
2/4✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
|
479 | (void)oldopts.get("encryption", &oldenc); |
| 16925 | } | ||
| 16926 | |||
| 16927 | /* Get value of new encryption option. */ | ||
| 16928 |
3/6✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 479 times.
|
479 | ut_ad(newopts.exists("encryption")); |
| 16929 | 479 | dd::String_type newenc; | |
| 16930 |
2/4✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
|
479 | (void)newopts.get("encryption", &newenc); |
| 16931 | |||
| 16932 | /* Validate new encryption option provided */ | ||
| 16933 | 479 | const char *encrypt = newenc.data(); | |
| 16934 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 433 times.
|
479 | if (Encryption::validate_for_tablespace(encrypt) != DB_SUCCESS) { |
| 16935 | /* Incorrect encryption option */ | ||
| 16936 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); |
| 16937 |
1/2✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
|
46 | error = convert_error_code_to_mysql(DB_ERROR, 0, nullptr); |
| 16938 | 46 | return error; | |
| 16939 | } | ||
| 16940 | |||
| 16941 | /* If old tablespace definition says it's encrypted */ | ||
| 16942 | bool is_old_encrypted = | ||
| 16943 |
3/4✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 211 times.
✓ Branch 3 taken 222 times.
|
433 | !(oldenc.empty() || Encryption::is_none(oldenc.data())); |
| 16944 | /* If new tablespace definition says it's encrypted */ | ||
| 16945 | 433 | bool is_new_encrypted = !Encryption::is_none(newenc.data()); | |
| 16946 | 433 | fil_space_crypt_t *crypt_data = space->crypt_data; | |
| 16947 | |||
| 16948 | 433 | bool to_encrypt = false; | |
| 16949 | // It is only possible to mark tablespace to be skipped by encryption threads | ||
| 16950 | // if it is not already encrypted. | ||
| 16951 |
4/4✓ Branch 0 taken 222 times.
✓ Branch 1 taken 211 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 174 times.
|
433 | if (!is_old_encrypted && !is_new_encrypted && |
| 16952 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | alter_info->explicit_encryption) { |
| 16953 |
2/4✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
|
48 | if (!fil_crypt_exclude_tablespace_from_rotation_permanently(space)) { |
| 16954 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 16955 | } | ||
| 16956 | 48 | return error; | |
| 16957 |
3/4✓ Branch 0 taken 174 times.
✓ Branch 1 taken 211 times.
✓ Branch 2 taken 174 times.
✗ Branch 3 not taken.
|
385 | } else if (!is_old_encrypted && is_new_encrypted) { |
| 16958 |
3/4✓ Branch 0 taken 162 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
|
174 | DEBUG_SYNC_C("alter_encryption_to_y"); |
| 16959 |
2/4✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 174 times.
|
174 | if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) { |
| 16960 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 16961 | } | ||
| 16962 |
3/4✓ Branch 0 taken 162 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
|
174 | DEBUG_SYNC_C("alter_encryption_to_y_tablespace_excluded"); |
| 16963 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 158 times.
|
174 | if (crypt_data != nullptr) { |
| 16964 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | mutex_enter(&crypt_data->mutex); |
| 16965 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | ut_ad(crypt_data->type == CRYPT_SCHEME_UNENCRYPTED); |
| 16966 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | ut_ad(crypt_data->min_key_version == |
| 16967 | ENCRYPTION_KEY_VERSION_NOT_ENCRYPTED); | ||
| 16968 | // setting it to default - it could have been FIL_ENCRYPTION_N | ||
| 16969 | // however, now that it gets encrypted with Master Key encryption | ||
| 16970 | // the user will have a chance to re-encrypt it with KEYRING | ||
| 16971 | 16 | crypt_data->encryption = FIL_ENCRYPTION_DEFAULT; | |
| 16972 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | mutex_exit(&space->crypt_data->mutex); |
| 16973 | } | ||
| 16974 | /* Encrypt tablespace */ | ||
| 16975 | 174 | to_encrypt = true; | |
| 16976 |
3/4✓ Branch 0 taken 211 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
✓ Branch 3 taken 53 times.
|
211 | } else if (is_old_encrypted && !is_new_encrypted) { |
| 16977 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 146 times.
|
158 | if (crypt_data) { |
| 16978 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | mutex_enter(&crypt_data->mutex); |
| 16979 | 12 | bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED}; | |
| 16980 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | mutex_exit(&crypt_data->mutex); |
| 16981 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (is_keyring_encrypted) { |
| 16982 | ✗ | my_error(ER_EXPLICIT_DECRYPTION_OF_ONLINE_ENCRYPTED_TABLESPACE, MYF(0), | |
| 16983 | space->name); | ||
| 16984 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 16985 | } | ||
| 16986 | } | ||
| 16987 |
3/4✓ Branch 0 taken 144 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
|
158 | DEBUG_SYNC_C("alter_encryption_to_n"); |
| 16988 | // do not want master key decryption to get into way of encryption threads | ||
| 16989 |
2/4✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 158 times.
|
158 | if (!fil_crypt_exclude_tablespace_from_rotation_temporarily(space)) { |
| 16990 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 16991 | } | ||
| 16992 |
3/4✓ Branch 0 taken 144 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
|
158 | DEBUG_SYNC_C("alter_encryption_to_n_tablespace_excluded"); |
| 16993 | /* Unencrypt tablespace */ | ||
| 16994 | 158 | to_encrypt = false; | |
| 16995 | 158 | } else { | |
| 16996 | // If tablespace is encrypted by encryption threads - it cannot be | ||
| 16997 | // re-encrypted with Master Key encryption. It must first decrypted with | ||
| 16998 | // encryption threads. | ||
| 16999 |
3/4✓ Branch 0 taken 26 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
|
53 | if (space->crypt_data != nullptr && alter_info->explicit_encryption) { |
| 17000 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | mutex_enter(&crypt_data->mutex); |
| 17001 | 26 | bool is_keyring_encrypted{crypt_data->type != CRYPT_SCHEME_UNENCRYPTED}; | |
| 17002 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | mutex_exit(&crypt_data->mutex); |
| 17003 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
|
26 | if (is_keyring_encrypted) { |
| 17004 | ✗ | my_error(ER_ONLINE_KEYRING_TO_MK_RE_ENCRYPTION, MYF(0), space->name); | |
| 17005 | ✗ | return convert_error_code_to_mysql(DB_ERROR, 0, NULL); | |
| 17006 | } | ||
| 17007 | } | ||
| 17008 | /* Nothing to do */ | ||
| 17009 | 53 | return error; | |
| 17010 | } | ||
| 17011 | |||
| 17012 | /* Get the transaction associated with the current thd */ | ||
| 17013 |
1/2✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
|
332 | trx = check_trx_exists(thd); |
| 17014 |
1/2✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
|
332 | innobase_register_trx(hton, thd, trx); |
| 17015 | |||
| 17016 |
1/2✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
|
332 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 17017 | |||
| 17018 |
4/6✓ Branch 0 taken 332 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 326 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
332 | DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_before_processing", |
| 17019 | DBUG_SUICIDE();); | ||
| 17020 | |||
| 17021 | /* do encryption/unencryption processing now. */ | ||
| 17022 |
1/2✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
|
326 | err = fsp_alter_encrypt_tablespace(thd, space_id, to_encrypt, new_dd_space); |
| 17023 | |||
| 17024 |
4/6✓ Branch 0 taken 245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 239 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
245 | DBUG_EXECUTE_IF("alter_encrypt_tablespace_crash_after_processing", |
| 17025 | DBUG_SUICIDE();); | ||
| 17026 | |||
| 17027 |
1/2✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
|
239 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 17028 | 239 | return error; | |
| 17029 | 402 | } | |
| 17030 | |||
| 17031 | /** ALTER an undo tablespace. | ||
| 17032 | @param[in] hton Handlerton of InnoDB | ||
| 17033 | @param[in] thd Connection | ||
| 17034 | @param[in] alter_info How to do the command | ||
| 17035 | @param[in] old_dd_space Tablespace metadata | ||
| 17036 | @param[in] new_dd_space Tablespace metadata | ||
| 17037 | @return MySQL error code*/ | ||
| 17038 | 5600 | static int innodb_alter_tablespace(handlerton *hton, THD *thd, | |
| 17039 | st_alter_tablespace *alter_info, | ||
| 17040 | const dd::Tablespace *old_dd_space, | ||
| 17041 | dd::Tablespace *new_dd_space) { | ||
| 17042 | 5600 | space_id_t space_id = SPACE_UNKNOWN; | |
| 17043 | ulint old_size, new_size; | ||
| 17044 | |||
| 17045 |
1/2✓ Branch 0 taken 5600 times.
✗ Branch 1 not taken.
|
5600 | DBUG_TRACE; |
| 17046 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5600 times.
|
5600 | assert(hton == innodb_hton_ptr); |
| 17047 | |||
| 17048 |
2/2✓ Branch 0 taken 5529 times.
✓ Branch 1 taken 71 times.
|
5600 | if (alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_RENAME && |
| 17049 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5511 times.
|
5529 | alter_info->ts_alter_tablespace_type != ALTER_TABLESPACE_OPTIONS) { |
| 17050 | 18 | return HA_ADMIN_NOT_IMPLEMENTED; | |
| 17051 | } | ||
| 17052 | |||
| 17053 | /* Name validation should be ensured from the SQL layer. */ | ||
| 17054 |
2/4✓ Branch 0 taken 5582 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5582 times.
|
5582 | ut_ad(0 == validate_tablespace_name(ALTER_TABLESPACE, |
| 17055 | alter_info->tablespace_name)); | ||
| 17056 | |||
| 17057 | /* Be sure that this tablespace is known and valid. */ | ||
| 17058 |
3/6✓ Branch 0 taken 5582 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5581 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
11164 | if (old_dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 17059 | 5582 | &space_id) || | |
| 17060 |
8/14✓ Branch 0 taken 5582 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5582 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5582 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5582 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5582 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 5581 times.
✓ Branch 12 taken 5582 times.
✗ Branch 13 not taken.
|
11164 | space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) { |
| 17061 | 1 | return HA_ERR_TABLESPACE_MISSING; | |
| 17062 | } | ||
| 17063 | |||
| 17064 |
3/4✓ Branch 0 taken 5581 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5580 times.
|
5581 | if (fsp_is_undo_tablespace(space_id)) { |
| 17065 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 17066 | "Cannot ALTER TABLESPACE `%s` because it is an undo " | ||
| 17067 | "tablespace. Please use ALTER UNDO TABLESPACE.", | ||
| 17068 | MYF(0), alter_info->tablespace_name); | ||
| 17069 | |||
| 17070 | 1 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 17071 | } | ||
| 17072 | |||
| 17073 | /* ALTER_TABLESPACE_OPTIONS */ | ||
| 17074 |
2/2✓ Branch 0 taken 5511 times.
✓ Branch 1 taken 69 times.
|
5580 | if (alter_info->ts_alter_tablespace_type == ALTER_TABLESPACE_OPTIONS) { |
| 17075 | 5511 | int err = 0; | |
| 17076 | /* Process the encryption option if specified with the | ||
| 17077 | ALTER TABLESPACE statement. */ | ||
| 17078 |
2/2✓ Branch 0 taken 495 times.
✓ Branch 1 taken 5016 times.
|
6006 | if (alter_info->encryption != nullptr && |
| 17079 |
8/14✓ Branch 0 taken 495 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 495 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 495 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 495 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 495 times.
✓ Branch 9 taken 5016 times.
✓ Branch 10 taken 495 times.
✓ Branch 11 taken 5016 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
6006 | new_dd_space->options().exists("encryption")) { |
| 17080 |
1/2✓ Branch 0 taken 402 times.
✗ Branch 1 not taken.
|
495 | err = innobase_alter_encrypt_tablespace(hton, thd, alter_info, |
| 17081 | old_dd_space, new_dd_space); | ||
| 17082 | } | ||
| 17083 | |||
| 17084 | /* Process the AUTOEXTEND_SIZE clause if mentioned with | ||
| 17085 | the ALTER TABLESPACE statement. */ | ||
| 17086 |
4/4✓ Branch 0 taken 5353 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 5015 times.
✓ Branch 3 taken 338 times.
|
10433 | if (!err && alter_info->autoextend_size.has_value() && |
| 17087 |
8/14✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5015 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5015 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5015 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5015 times.
✓ Branch 9 taken 403 times.
✓ Branch 10 taken 5015 times.
✓ Branch 11 taken 403 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
10433 | new_dd_space->options().exists(autoextend_size_str)) { |
| 17088 |
1/2✓ Branch 0 taken 5015 times.
✗ Branch 1 not taken.
|
5015 | err = innobase_alter_autoextend_size_tablespace(hton, alter_info, |
| 17089 | old_dd_space); | ||
| 17090 | } | ||
| 17091 | |||
| 17092 | /* Ignore any other ALTER TABLESPACE options. */ | ||
| 17093 | 5418 | return err; | |
| 17094 | } | ||
| 17095 | |||
| 17096 | /* ALTER_TABLESPACE_RENAME */ | ||
| 17097 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | const char *from = old_dd_space->name().c_str(); |
| 17098 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | const char *to = new_dd_space->name().c_str(); |
| 17099 | |||
| 17100 | /* mysql tablespace can't be renamed */ | ||
| 17101 |
2/4✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
|
69 | if (innobase_strcasecmp(from, dict_sys_t::s_dd_space_name) == 0) { |
| 17102 | ✗ | my_printf_error(ER_WRONG_TABLESPACE_NAME, | |
| 17103 | "InnoDB: `mysql` is a reserved" | ||
| 17104 | " tablespace name.", | ||
| 17105 | MYF(0)); | ||
| 17106 | ✗ | return HA_WRONG_CREATE_OPTION; | |
| 17107 | } | ||
| 17108 | |||
| 17109 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | ut_ad(ut_strcmp(from, to) != 0); |
| 17110 | |||
| 17111 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | dberr_t err = fil_rename_tablespace_by_id(space_id, from, to); |
| 17112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | if (err != DB_SUCCESS) { |
| 17113 | ✗ | return convert_error_code_to_mysql(err, 0, nullptr); | |
| 17114 | } | ||
| 17115 | |||
| 17116 | /* Rename any in-memory cached table->tablespace */ | ||
| 17117 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | dict_sys_mutex_enter(); |
| 17118 |
6/10✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2964 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3033 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2964 times.
✓ Branch 9 taken 69 times.
|
3033 | for (auto table : dict_sys->table_LRU) { |
| 17119 |
6/6✓ Branch 0 taken 2822 times.
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 2736 times.
✓ Branch 4 taken 86 times.
✓ Branch 5 taken 2878 times.
|
2964 | if (table->tablespace && strcmp(from, table->tablespace) == 0) { |
| 17120 |
1/2✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
|
86 | old_size = mem_heap_get_size(table->heap); |
| 17121 | |||
| 17122 |
1/2✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
|
86 | table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to)); |
| 17123 | |||
| 17124 |
1/2✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
|
86 | new_size = mem_heap_get_size(table->heap); |
| 17125 | 86 | dict_sys->size += new_size - old_size; | |
| 17126 | } | ||
| 17127 | } | ||
| 17128 | |||
| 17129 |
6/10✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1741 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1810 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1741 times.
✓ Branch 9 taken 69 times.
|
1810 | for (auto table : dict_sys->table_non_LRU) { |
| 17130 |
4/6✓ Branch 0 taken 1648 times.
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1648 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1741 times.
|
1741 | if (table->tablespace && strcmp(from, table->tablespace) == 0) { |
| 17131 | ✗ | old_size = mem_heap_get_size(table->heap); | |
| 17132 | |||
| 17133 | ✗ | table->tablespace = mem_heap_strdupl(table->heap, to, strlen(to)); | |
| 17134 | |||
| 17135 | ✗ | new_size = mem_heap_get_size(table->heap); | |
| 17136 | ✗ | dict_sys->size += new_size - old_size; | |
| 17137 | } | ||
| 17138 | } | ||
| 17139 | |||
| 17140 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | dict_sys_mutex_exit(); |
| 17141 | |||
| 17142 | 69 | return 0; | |
| 17143 | 5507 | } | |
| 17144 | |||
| 17145 | /** DROP a tablespace. | ||
| 17146 | @param[in] hton Handlerton of InnoDB | ||
| 17147 | @param[in] thd Connection | ||
| 17148 | @param[in] alter_info How to do the command | ||
| 17149 | @param[in] dd_space Tablespace metadata | ||
| 17150 | @return MySQL error code*/ | ||
| 17151 | 885 | static int innodb_drop_tablespace(handlerton *hton, THD *thd, | |
| 17152 | st_alter_tablespace *alter_info, | ||
| 17153 | const dd::Tablespace *dd_space) { | ||
| 17154 | 885 | int error = 0; | |
| 17155 | 885 | space_id_t space_id = SPACE_UNKNOWN; | |
| 17156 | |||
| 17157 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | DBUG_TRACE; |
| 17158 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
|
885 | assert(hton == innodb_hton_ptr); |
| 17159 | |||
| 17160 |
2/4✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 885 times.
✗ Branch 3 not taken.
|
885 | auto dd_space_name = dd_space->name(); |
| 17161 | |||
| 17162 |
2/4✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 885 times.
|
885 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 17163 | |||
| 17164 | /* Name validation should be ensured from the SQL layer. */ | ||
| 17165 |
2/4✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 885 times.
|
885 | ut_ad(0 == |
| 17166 | validate_tablespace_name(DROP_TABLESPACE, alter_info->tablespace_name)); | ||
| 17167 | |||
| 17168 | /* Be sure that this tablespace is known and valid. */ | ||
| 17169 |
2/6✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 885 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
1770 | if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 17170 |
4/8✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 885 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 885 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 885 times.
✗ Branch 7 not taken.
|
2655 | &space_id) || |
| 17171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
|
885 | space_id == SPACE_UNKNOWN) { |
| 17172 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 17173 | } | ||
| 17174 | |||
| 17175 |
3/4✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 884 times.
|
885 | if (fsp_is_undo_tablespace(space_id)) { |
| 17176 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 17177 | "Cannot DROP TABLESPACE `%s` because it is an undo " | ||
| 17178 | "tablespace. Please use DROP UNDO TABLESPACE.", | ||
| 17179 | MYF(0), alter_info->tablespace_name); | ||
| 17180 | |||
| 17181 | 1 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 17182 | } | ||
| 17183 | |||
| 17184 |
3/4✓ Branch 0 taken 884 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 880 times.
|
884 | if (fil_space_get_flags(space_id) == UINT32_UNDEFINED) { |
| 17185 | /* The DD knows about it but the actual tablespace is missing. | ||
| 17186 | Allow it to be dropped from the DD. */ | ||
| 17187 | 4 | return 0; | |
| 17188 | } | ||
| 17189 | |||
| 17190 | /* Get the transaction associated with the current thd. */ | ||
| 17191 |
1/2✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
|
880 | trx_t *trx = check_trx_exists(thd); |
| 17192 |
1/2✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
|
880 | TrxInInnoDB trx_in_innodb(trx); |
| 17193 |
1/2✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
|
880 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 17194 | 880 | ++trx->will_lock; | |
| 17195 | |||
| 17196 | /* Acquire Exclusive MDL on SDI table of tablespace. | ||
| 17197 | This is to prevent concurrent purge on SDI table */ | ||
| 17198 | 880 | MDL_ticket *sdi_mdl = nullptr; | |
| 17199 |
1/2✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
|
880 | dberr_t err = dd_sdi_acquire_exclusive_mdl(thd, space_id, &sdi_mdl); |
| 17200 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 880 times.
|
880 | if (err != DB_SUCCESS) { |
| 17201 | ✗ | error = convert_error_code_to_mysql(err, 0, nullptr); | |
| 17202 | ✗ | return error; | |
| 17203 | } | ||
| 17204 | |||
| 17205 |
2/4✓ Branch 0 taken 880 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 880 times.
✗ Branch 3 not taken.
|
880 | err = log_ddl->write_delete_space_log(trx, nullptr, space_id, |
| 17206 | dd_tablespace_get_filename(dd_space), | ||
| 17207 | true, false); | ||
| 17208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 880 times.
|
880 | if (err != DB_SUCCESS) { |
| 17209 | ✗ | error = convert_error_code_to_mysql(err, 0, nullptr); | |
| 17210 | } | ||
| 17211 | |||
| 17212 | 880 | return error; | |
| 17213 | 885 | } | |
| 17214 | |||
| 17215 | /** CREATE an undo tablespace. | ||
| 17216 | @param[in] hton Handlerton of InnoDB | ||
| 17217 | @param[in] thd Connection | ||
| 17218 | @param[in] alter_info How to do the command | ||
| 17219 | @param[in,out] dd_space Tablespace metadata | ||
| 17220 | @return MySQL error code*/ | ||
| 17221 | 376 | static int innodb_create_undo_tablespace(handlerton *hton, THD *thd, | |
| 17222 | st_alter_tablespace *alter_info, | ||
| 17223 | dd::Tablespace *dd_space) { | ||
| 17224 | 376 | int error = 0; | |
| 17225 | dberr_t err; | ||
| 17226 | uint32_t flags; | ||
| 17227 | |||
| 17228 |
1/2✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
|
376 | DBUG_TRACE; |
| 17229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
|
376 | assert(hton == innodb_hton_ptr); |
| 17230 | |||
| 17231 |
2/4✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 376 times.
|
376 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 17232 |
2/4✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 376 times.
|
376 | ut_ad(strcmp(alter_info->data_file_name, |
| 17233 | dd_tablespace_get_filename(dd_space)) == 0); | ||
| 17234 | |||
| 17235 | /* Be sure the input parameters are valid before continuing. */ | ||
| 17236 |
1/2✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
|
376 | error = validate_create_tablespace_info(IBU, alter_info); |
| 17237 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 361 times.
|
376 | if (error) { |
| 17238 | 15 | return error; | |
| 17239 | } | ||
| 17240 | |||
| 17241 | /* Notify clone about the UNDO DDL and possibly wait. We don't | ||
| 17242 | need similar notification for drop which is recoverable with DDL | ||
| 17243 | log. */ | ||
| 17244 | Clone_notify notifier(Clone_notify::Type::SPACE_UNDO_DDL, | ||
| 17245 |
1/2✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
|
361 | dict_sys_t::s_invalid_space_id, false); |
| 17246 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 360 times.
|
361 | if (notifier.failed()) { |
| 17247 | 1 | return notifier.get_error(); | |
| 17248 | } | ||
| 17249 | |||
| 17250 | /* Create the tablespace object. */ | ||
| 17251 | |||
| 17252 | /* Serialize all undo tablespace DDLs */ | ||
| 17253 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | mutex_enter(&undo::ddl_mutex); |
| 17254 | |||
| 17255 | /* Get the transaction associated with the current thd and make | ||
| 17256 | sure it will not block this DDL. */ | ||
| 17257 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | check_trx_exists(thd); |
| 17258 | |||
| 17259 | /* Allocate a new transaction for this DDL */ | ||
| 17260 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | trx_t *trx = innobase_trx_allocate(thd); |
| 17261 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 17262 | 360 | ++trx->will_lock; | |
| 17263 | |||
| 17264 | /* Find the next available undo space number and mark it in-use. */ | ||
| 17265 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | space_id_t space_id = undo::get_next_available_space_num(); |
| 17266 |
5/6✓ Branch 0 taken 359 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 359 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 359 times.
|
719 | if (space_id == SPACE_UNKNOWN || |
| 17267 | 359 | undo::spaces->size() == FSP_MAX_UNDO_TABLESPACES) { | |
| 17268 | /* All available explicit undo tablespaces have been used. */ | ||
| 17269 | 1 | ib::error(ER_IB_MSG_MAX_UNDO_SPACES_REACHED, alter_info->tablespace_name, | |
| 17270 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | alter_info->data_file_name, int{FSP_MAX_UNDO_TABLESPACES}); |
| 17271 | 1 | error = HA_ERR_TABLESPACE_EXISTS; | |
| 17272 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | trx_rollback_for_mysql(trx); |
| 17273 | 1 | goto cleanup; | |
| 17274 | } | ||
| 17275 | |||
| 17276 |
1/2✓ Branch 0 taken 359 times.
✗ Branch 1 not taken.
|
359 | err = srv_undo_tablespace_create(alter_info->tablespace_name, |
| 17277 | alter_info->data_file_name, space_id); | ||
| 17278 | |||
| 17279 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 357 times.
|
359 | if (err != DB_SUCCESS) { |
| 17280 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | error = convert_error_code_to_mysql(err, 0, nullptr); |
| 17281 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_rollback_for_mysql(trx); |
| 17282 | 2 | goto cleanup; | |
| 17283 | } | ||
| 17284 | |||
| 17285 |
1/2✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
|
357 | innobase_commit_low(trx); |
| 17286 | |||
| 17287 | /* Make sure the DD has the space_id and the flags. */ | ||
| 17288 |
1/2✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
|
357 | flags = fsp_flags_init(univ_page_size, false, false, false, false); |
| 17289 |
1/2✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
|
357 | dd_write_tablespace(dd_space, space_id, flags, DD_SPACE_STATE_ACTIVE); |
| 17290 | |||
| 17291 | /* Mark the undo tablespace 'active' in undo::spaces. */ | ||
| 17292 |
1/2✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
|
357 | undo::set_active(space_id); |
| 17293 |
1/2✓ Branch 0 taken 357 times.
✗ Branch 1 not taken.
|
357 | ut_d(ib::info(ER_IB_MSG_UNDO_MARKED_ACTIVE, alter_info->tablespace_name)); |
| 17294 | |||
| 17295 | 360 | cleanup: | |
| 17296 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | trx_free_for_mysql(trx); |
| 17297 | |||
| 17298 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | mutex_exit(&undo::ddl_mutex); |
| 17299 | |||
| 17300 |
1/2✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
|
360 | ib::info(ER_IB_MSG_CREATED_UNDO_SPACE, alter_info->tablespace_name); |
| 17301 | |||
| 17302 | 360 | return error; | |
| 17303 | 376 | } | |
| 17304 | |||
| 17305 | /** ALTER an undo tablespace to ACTIVE. | ||
| 17306 | @param[in] undo_space Undo Tablespace object | ||
| 17307 | @param[in] dd_state Current state in the DD. | ||
| 17308 | @param[in] dd_space Tablespace metadata | ||
| 17309 | @return MySQL error code*/ | ||
| 17310 | 213 | static int innodb_alter_undo_tablespace_active(undo::Tablespace *undo_space, | |
| 17311 | dd::String_type dd_state, | ||
| 17312 | dd::Tablespace *dd_space) { | ||
| 17313 | /* Change the state of the undo tablespace. | ||
| 17314 | ALTER UNDO TABLESPACE is idempotent. */ | ||
| 17315 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 4 times.
|
213 | if (dd_state != dd_space_state_values[DD_SPACE_STATE_ACTIVE]) { |
| 17316 | 209 | dd_tablespace_set_state(dd_space, DD_SPACE_STATE_ACTIVE); | |
| 17317 | } | ||
| 17318 | |||
| 17319 | /* Start using this undo tablespace. */ | ||
| 17320 | 213 | undo_space->alter_active(); | |
| 17321 | |||
| 17322 | 213 | return (0); | |
| 17323 | } | ||
| 17324 | |||
| 17325 | /** ALTER an undo tablespace to INACTIVE. | ||
| 17326 | @param[in] undo_space Undo Tablespace object | ||
| 17327 | @param[in] dd_state Current state in the DD. | ||
| 17328 | @param[in] dd_space Tablespace metadata | ||
| 17329 | @return MySQL error code*/ | ||
| 17330 | 574 | static int innodb_alter_undo_tablespace_inactive(undo::Tablespace *undo_space, | |
| 17331 | dd::String_type dd_state, | ||
| 17332 | dd::Tablespace *dd_space) { | ||
| 17333 | /* If it is already empty, just return. */ | ||
| 17334 |
5/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 571 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 571 times.
|
577 | if (undo_space->is_empty() && |
| 17335 | 3 | dd_state == dd_space_state_values[DD_SPACE_STATE_EMPTY]) { | |
| 17336 | 3 | return (0); | |
| 17337 | } | ||
| 17338 | |||
| 17339 |
2/2✓ Branch 0 taken 538 times.
✓ Branch 1 taken 33 times.
|
571 | if (undo_space->is_active()) { |
| 17340 | /* There must be at least 2 active undo tablespaces besides the one we | ||
| 17341 | are trying to make inactive explicitly. One of those two could be in | ||
| 17342 | the process of being implicitly truncated. So if one other space is | ||
| 17343 | inactive_implicit, then it is being truncated and will be put back | ||
| 17344 | to active before this undo_space is truncated. */ | ||
| 17345 | 538 | ulint other_active_spaces = 0; | |
| 17346 |
2/2✓ Branch 0 taken 18784 times.
✓ Branch 1 taken 538 times.
|
19322 | for (auto undo_ts : undo::spaces->m_spaces) { |
| 17347 |
2/2✓ Branch 0 taken 18246 times.
✓ Branch 1 taken 538 times.
|
18784 | if (undo_ts != undo_space) { |
| 17348 |
3/4✓ Branch 0 taken 18246 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9636 times.
✓ Branch 3 taken 8610 times.
|
18246 | if (undo_ts->is_active()) { |
| 17349 | 9636 | other_active_spaces++; | |
| 17350 |
5/6✓ Branch 0 taken 8610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 8593 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 8593 times.
|
8627 | } else if (undo_ts->is_inactive_implicit() && |
| 17351 | 17 | purge_sys->undo_trunc.get_marked_space_num() == | |
| 17352 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | undo_ts->num()) { |
| 17353 | 17 | other_active_spaces++; | |
| 17354 | } | ||
| 17355 | } | ||
| 17356 | } | ||
| 17357 | |||
| 17358 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 524 times.
|
538 | if (other_active_spaces < 2) { |
| 17359 | 14 | my_printf_error(ER_DISALLOWED_OPERATION, | |
| 17360 | "Cannot set %s inactive since there would be" | ||
| 17361 | " less than 2 undo tablespaces left active.", | ||
| 17362 | MYF(0), undo_space->space_name()); | ||
| 17363 | |||
| 17364 | 14 | return (HA_ERR_NOT_ALLOWED_COMMAND); | |
| 17365 | } | ||
| 17366 | } | ||
| 17367 | |||
| 17368 | /* If truncation is happening too often on this undo tablespace there | ||
| 17369 | may be too many old files still in the fil_system with their pages | ||
| 17370 | still in the buffer pool. If this is the case, return an error. */ | ||
| 17371 | 557 | auto count = fil_count_undo_deleted(undo_space->num()); | |
| 17372 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 557 times.
|
557 | if (count > CONCURRENT_UNDO_TRUNCATE_LIMIT) { |
| 17373 | ✗ | my_printf_error(ER_DISALLOWED_OPERATION, | |
| 17374 | "Cannot set %s inactive since there would be more" | ||
| 17375 | " than %zu old versions of this undo tablespace" | ||
| 17376 | " in cache. Please wait for the next checkpoint.", | ||
| 17377 | MYF(0), undo_space->space_name(), | ||
| 17378 | CONCURRENT_UNDO_TRUNCATE_LIMIT); | ||
| 17379 | |||
| 17380 | ✗ | return (HA_ERR_NOT_ALLOWED_COMMAND); | |
| 17381 | } | ||
| 17382 | |||
| 17383 | /* Make sure the DD shows inactive if it is active. */ | ||
| 17384 | 557 | dd_tablespace_set_state(dd_space, DD_SPACE_STATE_INACTIVE); | |
| 17385 | |||
| 17386 | /* Apply this to new transactions. */ | ||
| 17387 | 557 | undo_space->set_inactive_explicit(); | |
| 17388 |
1/2✓ Branch 0 taken 557 times.
✗ Branch 1 not taken.
|
557 | ut_d(ib::info(ER_IB_MSG_UNDO_ALTERED_INACTIVE, undo_space->file_name())); |
| 17389 | |||
| 17390 | 557 | srv_wake_purge_thread_if_not_active(); | |
| 17391 | |||
| 17392 | 557 | return (0); | |
| 17393 | } | ||
| 17394 | |||
| 17395 | /** ALTER an undo tablespace. Either make it ACTIVE or INACTIVE. | ||
| 17396 | @param[in] hton Handlerton of InnoDB | ||
| 17397 | @param[in] alter_info How to do the command | ||
| 17398 | @param[in] dd_space Tablespace metadata | ||
| 17399 | @return MySQL error code*/ | ||
| 17400 | 789 | static int innodb_alter_undo_tablespace(handlerton *hton, | |
| 17401 | st_alter_tablespace *alter_info, | ||
| 17402 | dd::Tablespace *dd_space) { | ||
| 17403 | 789 | space_id_t space_id = SPACE_UNKNOWN; | |
| 17404 | |||
| 17405 |
1/2✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
|
789 | DBUG_TRACE; |
| 17406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 789 times.
|
789 | assert(hton == innodb_hton_ptr); |
| 17407 | |||
| 17408 |
2/4✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 789 times.
|
789 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 17409 | |||
| 17410 | /* Name validation should be ensured from the SQL layer. */ | ||
| 17411 |
2/4✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 789 times.
|
789 | ut_ad(0 == validate_tablespace_name(ALTER_UNDO_TABLESPACE, |
| 17412 | alter_info->tablespace_name)); | ||
| 17413 | |||
| 17414 | /* Be sure that this tablespace is known and valid. */ | ||
| 17415 |
2/6✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 789 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
1578 | if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 17416 | 789 | &space_id) || | |
| 17417 |
7/14✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 789 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 789 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 789 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 789 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 789 times.
✓ Branch 12 taken 789 times.
✗ Branch 13 not taken.
|
1578 | space_id == SPACE_UNKNOWN || fil_space_get_size(space_id) == 0) { |
| 17418 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 17419 | } | ||
| 17420 | |||
| 17421 |
3/4✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 787 times.
|
789 | if (!fsp_is_undo_tablespace(space_id)) { |
| 17422 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 17423 | "Cannot ALTER UNDO TABLESPACE `%s` because it is a " | ||
| 17424 | "general tablespace. Please use ALTER TABLESPACE.", | ||
| 17425 | MYF(0), alter_info->tablespace_name); | ||
| 17426 | |||
| 17427 | 2 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 17428 | } | ||
| 17429 | |||
| 17430 | /* Get the current state of the undo tablespace from the DD. */ | ||
| 17431 | 787 | dd::String_type dd_state; | |
| 17432 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | dd_tablespace_get_state(dd_space, &dd_state, space_id); |
| 17433 | |||
| 17434 | /* Serialize all undo tablespace DDLs */ | ||
| 17435 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | mutex_enter(&undo::ddl_mutex); |
| 17436 | |||
| 17437 | /* Get the current undo_space object. */ | ||
| 17438 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | undo::spaces->s_lock(); |
| 17439 | 787 | space_id_t space_num = undo::id2num(space_id); | |
| 17440 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | undo::Tablespace *undo_space = undo::spaces->find(space_num); |
| 17441 | |||
| 17442 | /* ALTER UNDO TABLESPACE is idempotent. */ | ||
| 17443 | 787 | int err = 0; | |
| 17444 |
2/3✓ Branch 0 taken 213 times.
✓ Branch 1 taken 574 times.
✗ Branch 2 not taken.
|
787 | switch (alter_info->ts_alter_tablespace_type) { |
| 17445 | 213 | case ALTER_UNDO_TABLESPACE_SET_ACTIVE: | |
| 17446 |
2/4✓ Branch 0 taken 213 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213 times.
✗ Branch 3 not taken.
|
213 | err = innodb_alter_undo_tablespace_active(undo_space, dd_state, dd_space); |
| 17447 | 213 | break; | |
| 17448 | |||
| 17449 | 574 | case ALTER_UNDO_TABLESPACE_SET_INACTIVE: | |
| 17450 | err = | ||
| 17451 |
2/4✓ Branch 0 taken 574 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 574 times.
✗ Branch 3 not taken.
|
574 | innodb_alter_undo_tablespace_inactive(undo_space, dd_state, dd_space); |
| 17452 | 574 | break; | |
| 17453 | |||
| 17454 | ✗ | default: | |
| 17455 | ✗ | err = HA_ADMIN_NOT_IMPLEMENTED; | |
| 17456 | } | ||
| 17457 | |||
| 17458 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | undo::spaces->s_unlock(); |
| 17459 | |||
| 17460 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | mutex_exit(&undo::ddl_mutex); |
| 17461 | |||
| 17462 | 787 | return err; | |
| 17463 | 789 | } | |
| 17464 | |||
| 17465 | /** DROP an undo tablespace. | ||
| 17466 | @param[in] hton Handlerton of InnoDB | ||
| 17467 | @param[in] thd Connection | ||
| 17468 | @param[in] alter_info How to do the command | ||
| 17469 | @param[in] dd_space Tablespace metadata | ||
| 17470 | @return MySQL error code*/ | ||
| 17471 | 342 | static int innodb_drop_undo_tablespace(handlerton *hton, THD *thd, | |
| 17472 | st_alter_tablespace *alter_info, | ||
| 17473 | const dd::Tablespace *dd_space) { | ||
| 17474 | 342 | space_id_t space_id = SPACE_UNKNOWN; | |
| 17475 | |||
| 17476 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | DBUG_TRACE; |
| 17477 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 342 times.
|
342 | assert(hton == innodb_hton_ptr); |
| 17478 | |||
| 17479 |
2/4✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 342 times.
|
342 | ut_ad(alter_info->tablespace_name == dd_space->name()); |
| 17480 | |||
| 17481 | /* Name validation should be ensured from the SQL layer. */ | ||
| 17482 |
2/4✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 342 times.
|
342 | ut_ad(0 == validate_tablespace_name(DROP_UNDO_TABLESPACE, |
| 17483 | alter_info->tablespace_name)); | ||
| 17484 | |||
| 17485 | /* Be sure that this tablespace is known and valid. */ | ||
| 17486 |
2/6✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 342 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
684 | if (dd_space->se_private_data().get(dd_space_key_strings[DD_SPACE_ID], |
| 17487 |
4/8✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 342 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 342 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 342 times.
✗ Branch 7 not taken.
|
1026 | &space_id) || |
| 17488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 342 times.
|
342 | space_id == SPACE_UNKNOWN) { |
| 17489 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 17490 | } | ||
| 17491 | |||
| 17492 |
3/4✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 341 times.
|
342 | if (!fsp_is_undo_tablespace(space_id)) { |
| 17493 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | my_printf_error(ER_WRONG_TABLESPACE_NAME, |
| 17494 | "Cannot DROP UNDO TABLESPACE `%s` because it is a " | ||
| 17495 | "general tablespace. Please use DROP TABLESPACE.", | ||
| 17496 | MYF(0), alter_info->tablespace_name); | ||
| 17497 | |||
| 17498 | 1 | return HA_ERR_NOT_ALLOWED_COMMAND; | |
| 17499 | } | ||
| 17500 | |||
| 17501 | /* Serialize all undo tablespace DDLs */ | ||
| 17502 |
1/2✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
|
341 | mutex_enter(&undo::ddl_mutex); |
| 17503 | |||
| 17504 |
1/2✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
|
341 | undo::spaces->x_lock(); |
| 17505 | 341 | space_id_t space_num = undo::id2num(space_id); | |
| 17506 |
1/2✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
|
341 | undo::Tablespace *undo_space = undo::spaces->find(space_num); |
| 17507 | |||
| 17508 | /* If the undo space is missing, allow the DROP UNDO TABLESPACE to | ||
| 17509 | continue to completion. */ | ||
| 17510 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 339 times.
|
341 | if (undo_space == nullptr) { |
| 17511 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | undo::spaces->x_unlock(); |
| 17512 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | mutex_exit(&undo::ddl_mutex); |
| 17513 | |||
| 17514 | /* Start the transaction associated with the current thd so that MySQL | ||
| 17515 | can continue. */ | ||
| 17516 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_t *trx = check_trx_exists(thd); |
| 17517 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 17518 | 2 | ++trx->will_lock; | |
| 17519 | |||
| 17520 | 2 | return (0); | |
| 17521 | } | ||
| 17522 | |||
| 17523 | /* Verify that the undo tablespace is not one of the first two undo spaces, | ||
| 17524 | has been altered inactive and is now empty. */ | ||
| 17525 |
4/6✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 335 times.
|
678 | if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES || |
| 17526 |
3/4✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 335 times.
|
339 | !undo_space->is_empty()) { |
| 17527 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ib::error err_msg; |
| 17528 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | err_msg << "Cannot drop undo tablespace '" << undo_space->space_name(); |
| 17529 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (undo_space->num() <= FSP_IMPLICIT_UNDO_TABLESPACES) { |
| 17530 | ✗ | err_msg << "' because it was not created explicitly."; | |
| 17531 |
3/10✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
|
4 | } else if (undo_space->is_active() || undo_space->is_inactive_implicit()) { |
| 17532 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | err_msg << "' because it is active. " |
| 17533 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | << "Please do: ALTER UNDO TABLESPACE " << undo_space->space_name() |
| 17534 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | << " SET INACTIVE;"; |
| 17535 | } else { | ||
| 17536 | err_msg << "' because it is still being truncated." | ||
| 17537 | ✗ | " Please try again later."; | |
| 17538 | } | ||
| 17539 | |||
| 17540 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | undo::spaces->x_unlock(); |
| 17541 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | mutex_exit(&undo::ddl_mutex); |
| 17542 | |||
| 17543 | 4 | return HA_ERR_TABLESPACE_IS_NOT_EMPTY; | |
| 17544 | 4 | } | |
| 17545 | |||
| 17546 | /* We don't need to invalidate buffer pool pages belonging to this undo | ||
| 17547 | tablespace before dropping it, as they will be set as stale and to be | ||
| 17548 | lazily freed. */ | ||
| 17549 | |||
| 17550 | /* Save the file name before undo_space is dropped. */ | ||
| 17551 |
2/4✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 335 times.
✗ Branch 3 not taken.
|
335 | std::string file_name{undo_space->file_name()}; |
| 17552 | |||
| 17553 | /* Empty and inactive, take it out of view. */ | ||
| 17554 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | undo::spaces->drop(undo_space); |
| 17555 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | undo::spaces->x_unlock(); |
| 17556 | |||
| 17557 | /* Get the transaction associated with the current thd and write a | ||
| 17558 | delete_space record to the DDL_LOG. */ | ||
| 17559 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | trx_t *trx = check_trx_exists(thd); |
| 17560 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | TrxInInnoDB trx_in_innodb(trx); |
| 17561 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | trx_start_if_not_started(trx, true, UT_LOCATION_HERE); |
| 17562 | 335 | ++trx->will_lock; | |
| 17563 | |||
| 17564 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | auto err = log_ddl->write_delete_space_log(trx, nullptr, space_id, |
| 17565 | file_name.c_str(), true, false); | ||
| 17566 | 335 | int error = 0; | |
| 17567 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
|
335 | if (err != DB_SUCCESS) { |
| 17568 | ✗ | error = convert_error_code_to_mysql(err, 0, nullptr); | |
| 17569 | } | ||
| 17570 | |||
| 17571 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | mutex_exit(&undo::ddl_mutex); |
| 17572 | |||
| 17573 |
1/2✓ Branch 0 taken 335 times.
✗ Branch 1 not taken.
|
335 | ib::info(ER_IB_MSG_DROPPED_UNDO_SPACE, alter_info->tablespace_name); |
| 17574 | |||
| 17575 | 335 | return error; | |
| 17576 | 342 | } | |
| 17577 | |||
| 17578 | /** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces. | ||
| 17579 | @param[in] hton Handlerton of InnoDB | ||
| 17580 | @param[in] thd Connection | ||
| 17581 | @param[in] alter_info Describes the command and how to do it. | ||
| 17582 | @param[in] old_ts_def Old version of dd::Tablespace object for the | ||
| 17583 | tablespace. | ||
| 17584 | @param[in,out] new_ts_def New version of dd::Tablespace object for the | ||
| 17585 | tablespace. Can be adjusted by SE. Changes will be persisted in the | ||
| 17586 | data-dictionary at statement commit. | ||
| 17587 | @return MySQL error code*/ | ||
| 17588 | 8971 | static int innobase_alter_tablespace(handlerton *hton, THD *thd, | |
| 17589 | st_alter_tablespace *alter_info, | ||
| 17590 | const dd::Tablespace *old_ts_def, | ||
| 17591 | dd::Tablespace *new_ts_def) { | ||
| 17592 | 8971 | int error = 0; /* return zero for success */ | |
| 17593 |
1/2✓ Branch 0 taken 8971 times.
✗ Branch 1 not taken.
|
8971 | DBUG_TRACE; |
| 17594 | |||
| 17595 |
4/4✓ Branch 0 taken 8970 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8969 times.
|
8971 | if (srv_read_only_mode || srv_force_recovery > 0) { |
| 17596 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | my_printf_error(ER_INNODB_READ_ONLY, |
| 17597 | "Changes to undo tablespaces are not allowed in" | ||
| 17598 | " %s mode", | ||
| 17599 | MYF(0), | ||
| 17600 | (srv_read_only_mode ? "read_only" : "force_recovery")); | ||
| 17601 | 2 | error = HA_ERR_INNODB_READ_ONLY; | |
| 17602 | 2 | goto handle_error; | |
| 17603 | } | ||
| 17604 | |||
| 17605 |
7/7✓ Branch 0 taken 974 times.
✓ Branch 1 taken 5600 times.
✓ Branch 2 taken 885 times.
✓ Branch 3 taken 376 times.
✓ Branch 4 taken 789 times.
✓ Branch 5 taken 342 times.
✓ Branch 6 taken 3 times.
|
8969 | switch (alter_info->ts_cmd_type) { |
| 17606 | 974 | case CREATE_TABLESPACE: | |
| 17607 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 974 times.
|
974 | ut_ad(new_ts_def != nullptr); |
| 17608 |
1/2✓ Branch 0 taken 972 times.
✗ Branch 1 not taken.
|
974 | error = innodb_create_tablespace(hton, thd, alter_info, new_ts_def); |
| 17609 | 972 | break; | |
| 17610 | |||
| 17611 | 5600 | case ALTER_TABLESPACE: | |
| 17612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5600 times.
|
5600 | ut_ad(old_ts_def != nullptr); |
| 17613 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5600 times.
|
5600 | ut_ad(new_ts_def != nullptr); |
| 17614 |
1/2✓ Branch 0 taken 5507 times.
✗ Branch 1 not taken.
|
5600 | error = innodb_alter_tablespace(hton, thd, alter_info, old_ts_def, |
| 17615 | new_ts_def); | ||
| 17616 | 5507 | break; | |
| 17617 | |||
| 17618 | 885 | case DROP_TABLESPACE: | |
| 17619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 885 times.
|
885 | ut_ad(old_ts_def != nullptr); |
| 17620 |
1/2✓ Branch 0 taken 885 times.
✗ Branch 1 not taken.
|
885 | error = innodb_drop_tablespace(hton, thd, alter_info, old_ts_def); |
| 17621 | 885 | break; | |
| 17622 | |||
| 17623 | 376 | case CREATE_UNDO_TABLESPACE: | |
| 17624 |
1/2✓ Branch 0 taken 376 times.
✗ Branch 1 not taken.
|
376 | error = innodb_create_undo_tablespace(hton, thd, alter_info, new_ts_def); |
| 17625 | 376 | break; | |
| 17626 | |||
| 17627 | 789 | case ALTER_UNDO_TABLESPACE: | |
| 17628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 789 times.
|
789 | ut_ad(new_ts_def != nullptr); |
| 17629 |
1/2✓ Branch 0 taken 789 times.
✗ Branch 1 not taken.
|
789 | error = innodb_alter_undo_tablespace(hton, alter_info, new_ts_def); |
| 17630 | 789 | break; | |
| 17631 | |||
| 17632 | 342 | case DROP_UNDO_TABLESPACE: | |
| 17633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 342 times.
|
342 | ut_ad(old_ts_def != nullptr); |
| 17634 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
342 | error = innodb_drop_undo_tablespace(hton, thd, alter_info, old_ts_def); |
| 17635 | 342 | break; | |
| 17636 | |||
| 17637 | 3 | default: | |
| 17638 | 3 | error = HA_ADMIN_NOT_IMPLEMENTED; | |
| 17639 | } | ||
| 17640 | |||
| 17641 | 8876 | handle_error: | |
| 17642 |
2/2✓ Branch 0 taken 220 times.
✓ Branch 1 taken 8656 times.
|
8876 | if (error) { |
| 17643 | /* These are the most common message params */ | ||
| 17644 | 220 | const char *ibd_type = "TABLESPACE"; | |
| 17645 | 220 | const char *undo_type = "UNDO TABLESPACE"; | |
| 17646 | 220 | uint32_t code = ER_CREATE_FILEGROUP_FAILED; | |
| 17647 | 220 | const char *subject = ibd_type; | |
| 17648 | |||
| 17649 | /* Modify those params as needed. */ | ||
| 17650 |
7/11✓ Branch 0 taken 87 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
220 | switch (alter_info->ts_cmd_type) { |
| 17651 | 87 | case CREATE_TABLESPACE: | |
| 17652 | 87 | break; | |
| 17653 | 87 | case ALTER_TABLESPACE: | |
| 17654 | 87 | code = ER_ALTER_FILEGROUP_FAILED; | |
| 17655 | 87 | break; | |
| 17656 | 2 | case DROP_TABLESPACE: | |
| 17657 | 2 | code = ER_DROP_FILEGROUP_FAILED; | |
| 17658 | 2 | break; | |
| 17659 | 20 | case CREATE_UNDO_TABLESPACE: | |
| 17660 | 20 | subject = undo_type; | |
| 17661 | 20 | break; | |
| 17662 | 16 | case ALTER_UNDO_TABLESPACE: | |
| 17663 | 16 | code = ER_ALTER_FILEGROUP_FAILED; | |
| 17664 | 16 | subject = undo_type; | |
| 17665 | 16 | break; | |
| 17666 | 5 | case DROP_UNDO_TABLESPACE: | |
| 17667 | 5 | code = ER_DROP_FILEGROUP_FAILED; | |
| 17668 | 5 | subject = undo_type; | |
| 17669 | 5 | break; | |
| 17670 | 3 | case CREATE_LOGFILE_GROUP: | |
| 17671 | case DROP_LOGFILE_GROUP: | ||
| 17672 | case ALTER_LOGFILE_GROUP: | ||
| 17673 | 3 | subject = "LOGFILE GROUP"; | |
| 17674 | 3 | break; | |
| 17675 | ✗ | case ALTER_ACCESS_MODE_TABLESPACE: | |
| 17676 | ✗ | subject = "ACCESS MODE"; | |
| 17677 | ✗ | break; | |
| 17678 | ✗ | case CHANGE_FILE_TABLESPACE: | |
| 17679 | ✗ | subject = "CHANGE FILE"; | |
| 17680 | ✗ | break; | |
| 17681 | ✗ | case TS_CMD_NOT_DEFINED: | |
| 17682 | ✗ | subject = "UNKNOWN"; | |
| 17683 | ✗ | break; | |
| 17684 | } | ||
| 17685 | |||
| 17686 |
2/3✓ Branch 0 taken 217 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
220 | switch (alter_info->ts_cmd_type) { |
| 17687 | 217 | case CREATE_TABLESPACE: | |
| 17688 | case ALTER_TABLESPACE: | ||
| 17689 | case DROP_TABLESPACE: | ||
| 17690 | case CREATE_UNDO_TABLESPACE: | ||
| 17691 | case ALTER_UNDO_TABLESPACE: | ||
| 17692 | case DROP_UNDO_TABLESPACE: | ||
| 17693 |
1/2✓ Branch 0 taken 217 times.
✗ Branch 1 not taken.
|
217 | ib_errf(thd, IB_LOG_LEVEL_ERROR, code, "%s %s", subject, |
| 17694 | alter_info->tablespace_name); | ||
| 17695 | 217 | break; | |
| 17696 | |||
| 17697 | 3 | case CREATE_LOGFILE_GROUP: | |
| 17698 | case ALTER_ACCESS_MODE_TABLESPACE: | ||
| 17699 | case DROP_LOGFILE_GROUP: | ||
| 17700 | case ALTER_LOGFILE_GROUP: | ||
| 17701 | case CHANGE_FILE_TABLESPACE: | ||
| 17702 | case TS_CMD_NOT_DEFINED: | ||
| 17703 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | my_error(ER_FEATURE_UNSUPPORTED, MYF(0), subject, "by InnoDB"); |
| 17704 | 3 | break; | |
| 17705 | } | ||
| 17706 | } | ||
| 17707 | |||
| 17708 | 8876 | return error; | |
| 17709 | 8876 | } | |
| 17710 | |||
| 17711 | /** Renames an InnoDB table. | ||
| 17712 | @param[in] from Old name of the table. | ||
| 17713 | @param[in] to New name of the table. | ||
| 17714 | @param[in] from_table_def dd::Table object describing old version | ||
| 17715 | of table. | ||
| 17716 | @param[in,out] to_table_def dd::Table object describing version of | ||
| 17717 | table with new name. Can be updated by SE. Changes are persisted to the | ||
| 17718 | dictionary at statement commit time. | ||
| 17719 | @return 0 or error code */ | ||
| 17720 | 14361 | int ha_innobase::rename_table(const char *from, const char *to, | |
| 17721 | const dd::Table *from_table_def, | ||
| 17722 | dd::Table *to_table_def) { | ||
| 17723 |
1/2✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
|
14361 | THD *thd = ha_thd(); |
| 17724 |
1/2✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
|
14361 | trx_t *trx = check_trx_exists(thd); |
| 17725 |
1/2✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
|
14361 | TrxInInnoDB trx_in_innodb(trx); |
| 17726 | |||
| 17727 |
1/2✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
|
14361 | DBUG_TRACE; |
| 17728 |
3/6✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14361 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14361 times.
|
14361 | ut_ad(from_table_def->se_private_id() == to_table_def->se_private_id()); |
| 17729 |
5/10✓ Branch 0 taken 14361 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14361 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14361 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14361 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 14361 times.
|
14361 | ut_ad(from_table_def->se_private_data().raw_string() == |
| 17730 | to_table_def->se_private_data().raw_string()); | ||
| 17731 | |||
| 17732 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14358 times.
|
14361 | if (high_level_read_only) { |
| 17733 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 17734 | 3 | return HA_ERR_TABLE_READONLY; | |
| 17735 | } | ||
| 17736 | |||
| 17737 |
4/6✓ Branch 0 taken 14358 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14358 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 14356 times.
|
14358 | if (dict_sys_t::is_dd_table_id(to_table_def->se_private_id())) { |
| 17738 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | my_error(ER_NOT_ALLOWED_COMMAND, MYF(0)); |
| 17739 | 2 | return HA_ERR_UNSUPPORTED; | |
| 17740 | } | ||
| 17741 | |||
| 17742 |
1/2✓ Branch 0 taken 14356 times.
✗ Branch 1 not taken.
|
14356 | innobase_register_trx(ht, thd, trx); |
| 17743 | |||
| 17744 |
1/2✓ Branch 0 taken 14311 times.
✗ Branch 1 not taken.
|
14356 | return innobase_basic_ddl::rename_impl<dd::Table>( |
| 17745 | 14311 | thd, from, to, from_table_def, to_table_def, nullptr); | |
| 17746 | 14316 | } | |
| 17747 | |||
| 17748 | /** Returns the exact number of records that this client can see using this | ||
| 17749 | handler object. | ||
| 17750 | @return Error code in case something goes wrong. | ||
| 17751 | These errors will abort the current query: | ||
| 17752 | case HA_ERR_LOCK_DEADLOCK: | ||
| 17753 | case HA_ERR_LOCK_TABLE_FULL: | ||
| 17754 | case HA_ERR_LOCK_WAIT_TIMEOUT: | ||
| 17755 | case HA_ERR_QUERY_INTERRUPTED: | ||
| 17756 | For other error codes, the server will fall back to counting records. */ | ||
| 17757 | |||
| 17758 | 34683 | int ha_innobase::records(ha_rows *num_rows) /*!< out: number of rows */ | |
| 17759 | { | ||
| 17760 |
1/2✓ Branch 0 taken 34683 times.
✗ Branch 1 not taken.
|
34683 | DBUG_TRACE; |
| 17761 | |||
| 17762 | dberr_t ret; | ||
| 17763 | 34683 | ulint n_rows = 0; /* Record count in this view */ | |
| 17764 | |||
| 17765 |
1/2✓ Branch 0 taken 34683 times.
✗ Branch 1 not taken.
|
34683 | update_thd(); |
| 17766 | |||
| 17767 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 34647 times.
|
34683 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 17768 | 36 | ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 17769 |
1/2✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
|
36 | table->s->table_name.str); |
| 17770 | |||
| 17771 | 36 | *num_rows = HA_POS_ERROR; | |
| 17772 | 36 | return HA_ERR_NO_SUCH_TABLE; | |
| 17773 | |||
| 17774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34647 times.
|
34647 | } else if (m_prebuilt->table->ibd_file_missing) { |
| 17775 | ✗ | ib_senderrf(m_user_thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING, | |
| 17776 | ✗ | table->s->table_name.str); | |
| 17777 | |||
| 17778 | ✗ | *num_rows = HA_POS_ERROR; | |
| 17779 | ✗ | return HA_ERR_TABLESPACE_MISSING; | |
| 17780 | |||
| 17781 |
2/4✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34647 times.
|
34647 | } else if (m_prebuilt->table->is_corrupted()) { |
| 17782 | ✗ | ib_errf(m_user_thd, IB_LOG_LEVEL_WARN, ER_INNODB_INDEX_CORRUPT, | |
| 17783 | ✗ | "Table '%s' is corrupt.", table->s->table_name.str); | |
| 17784 | |||
| 17785 | ✗ | *num_rows = HA_POS_ERROR; | |
| 17786 | ✗ | return HA_ERR_INDEX_CORRUPT; | |
| 17787 | } | ||
| 17788 | |||
| 17789 |
1/2✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
|
34647 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 17790 | |||
| 17791 | 34647 | m_prebuilt->trx->op_info = "counting records"; | |
| 17792 | |||
| 17793 |
1/2✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
|
34647 | dict_index_t *index = m_prebuilt->table->first_index(); |
| 17794 | |||
| 17795 |
2/4✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34647 times.
|
34647 | ut_ad(index->is_clustered()); |
| 17796 | |||
| 17797 |
1/2✓ Branch 0 taken 34647 times.
✗ Branch 1 not taken.
|
34647 | m_prebuilt->index_usable = index->is_usable(m_prebuilt->trx); |
| 17798 | |||
| 17799 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34646 times.
|
34647 | if (!m_prebuilt->index_usable) { |
| 17800 | 1 | *num_rows = HA_POS_ERROR; | |
| 17801 | 1 | return HA_ERR_TABLE_DEF_CHANGED; | |
| 17802 | } | ||
| 17803 | |||
| 17804 | /* (Re)Build the m_prebuilt->mysql_template if it is null to use | ||
| 17805 | the clustered index and just the key, no off-record data. */ | ||
| 17806 | 34646 | m_prebuilt->index = index; | |
| 17807 |
1/2✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
|
34646 | m_prebuilt->clear_search_tuples(); |
| 17808 | 34646 | m_prebuilt->read_just_key = 1; | |
| 17809 |
1/2✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
|
34646 | build_template(false); |
| 17810 | |||
| 17811 |
1/2✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
|
34646 | size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd); |
| 17812 | |||
| 17813 | /* Count the records in the clustered index */ | ||
| 17814 | ret = | ||
| 17815 |
1/2✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
|
34646 | row_scan_index_for_mysql(m_prebuilt, index, max_threads, false, &n_rows); |
| 17816 |
1/2✓ Branch 0 taken 34646 times.
✗ Branch 1 not taken.
|
34646 | reset_template(); |
| 17817 |
3/4✓ Branch 0 taken 34617 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
34646 | switch (ret) { |
| 17818 | 34617 | case DB_SUCCESS: | |
| 17819 | 34617 | break; | |
| 17820 | 27 | case DB_DEADLOCK: | |
| 17821 | case DB_LOCK_TABLE_FULL: | ||
| 17822 | case DB_LOCK_WAIT_TIMEOUT: | ||
| 17823 | 27 | *num_rows = HA_POS_ERROR; | |
| 17824 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | return convert_error_code_to_mysql(ret, 0, m_user_thd); |
| 17825 | 2 | case DB_INTERRUPTED: | |
| 17826 | 2 | *num_rows = HA_POS_ERROR; | |
| 17827 | 2 | return HA_ERR_QUERY_INTERRUPTED; | |
| 17828 | ✗ | default: | |
| 17829 | /* No other error besides the three below is returned from | ||
| 17830 | row_scan_index_for_mysql(). Make a debug catch. */ | ||
| 17831 | ✗ | *num_rows = HA_POS_ERROR; | |
| 17832 | ✗ | return -1; | |
| 17833 | } | ||
| 17834 | |||
| 17835 | 34617 | m_prebuilt->trx->op_info = ""; | |
| 17836 | |||
| 17837 |
2/4✓ Branch 0 taken 34617 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34617 times.
|
34617 | if (thd_killed(m_user_thd)) { |
| 17838 | ✗ | *num_rows = HA_POS_ERROR; | |
| 17839 | ✗ | return HA_ERR_QUERY_INTERRUPTED; | |
| 17840 | } | ||
| 17841 | |||
| 17842 | 34617 | *num_rows = n_rows; | |
| 17843 | 34617 | return 0; | |
| 17844 | 34683 | } | |
| 17845 | |||
| 17846 | /** Estimates the number of index records in a range. | ||
| 17847 | @return estimated number of rows */ | ||
| 17848 | |||
| 17849 | 487753 | ha_rows ha_innobase::records_in_range( | |
| 17850 | uint keynr, /*!< in: index number */ | ||
| 17851 | key_range *min_key, /*!< in: start key value of the | ||
| 17852 | range, may also be 0 */ | ||
| 17853 | key_range *max_key) /*!< in: range end key val, may | ||
| 17854 | also be 0 */ | ||
| 17855 | { | ||
| 17856 | KEY *key; | ||
| 17857 | dict_index_t *index; | ||
| 17858 | dtuple_t *range_start; | ||
| 17859 | dtuple_t *range_end; | ||
| 17860 | int64_t n_rows; | ||
| 17861 | page_cur_mode_t mode1; | ||
| 17862 | page_cur_mode_t mode2; | ||
| 17863 | mem_heap_t *heap; | ||
| 17864 | |||
| 17865 |
1/2✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
|
487753 | DBUG_TRACE; |
| 17866 | |||
| 17867 |
3/6✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 487754 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 487754 times.
|
487754 | ut_a(m_prebuilt->trx == thd_to_trx(ha_thd())); |
| 17868 | |||
| 17869 | 487754 | m_prebuilt->trx->op_info = "estimating records in index range"; | |
| 17870 | |||
| 17871 |
1/2✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
|
487754 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 17872 | |||
| 17873 | 487754 | active_index = keynr; | |
| 17874 | |||
| 17875 | 487754 | key = table->key_info + active_index; | |
| 17876 | |||
| 17877 |
1/2✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
|
487754 | index = innobase_get_index(keynr); |
| 17878 | |||
| 17879 | /* There exists possibility of not being able to find requested | ||
| 17880 | index due to inconsistency between MySQL and InoDB dictionary info. | ||
| 17881 | Necessary message should have been printed in innobase_get_index() */ | ||
| 17882 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 487754 times.
|
487754 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 17883 | ✗ | n_rows = HA_POS_ERROR; | |
| 17884 | ✗ | goto func_exit; | |
| 17885 | } | ||
| 17886 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 487754 times.
|
487754 | if (!index) { |
| 17887 | ✗ | n_rows = HA_POS_ERROR; | |
| 17888 | ✗ | goto func_exit; | |
| 17889 | } | ||
| 17890 |
3/4✓ Branch 0 taken 487754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 487746 times.
|
487754 | if (index->is_corrupted()) { |
| 17891 | 8 | n_rows = HA_ERR_INDEX_CORRUPT; | |
| 17892 | 8 | goto func_exit; | |
| 17893 | } | ||
| 17894 |
3/4✓ Branch 0 taken 487746 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 487744 times.
|
487746 | if (!index->is_usable(m_prebuilt->trx)) { |
| 17895 | 2 | n_rows = HA_ERR_TABLE_DEF_CHANGED; | |
| 17896 | 2 | goto func_exit; | |
| 17897 | } | ||
| 17898 | |||
| 17899 | 975488 | heap = mem_heap_create( | |
| 17900 |
1/2✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
|
487744 | 2 * (key->actual_key_parts * sizeof(dfield_t) + sizeof(dtuple_t)), |
| 17901 | UT_LOCATION_HERE); | ||
| 17902 | |||
| 17903 |
1/2✓ Branch 0 taken 487743 times.
✗ Branch 1 not taken.
|
487744 | range_start = dtuple_create(heap, key->actual_key_parts); |
| 17904 |
1/2✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
|
487743 | dict_index_copy_types(range_start, index, key->actual_key_parts); |
| 17905 | |||
| 17906 |
1/2✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
|
487744 | range_end = dtuple_create(heap, key->actual_key_parts); |
| 17907 |
1/2✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
|
487744 | dict_index_copy_types(range_end, index, key->actual_key_parts); |
| 17908 | |||
| 17909 |
4/4✓ Branch 0 taken 482327 times.
✓ Branch 1 taken 5417 times.
✓ Branch 2 taken 482327 times.
✓ Branch 3 taken 5417 times.
|
970071 | row_sel_convert_mysql_key_to_innobase( |
| 17910 |
1/2✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
|
487744 | range_start, m_prebuilt->srch_key_val1, m_prebuilt->srch_key_val_len, |
| 17911 | index, (byte *)(min_key ? min_key->key : (const uchar *)nullptr), | ||
| 17912 | 482327 | (ulint)(min_key ? min_key->length : 0)); | |
| 17913 | |||
| 17914 |
3/4✓ Branch 0 taken 482327 times.
✓ Branch 1 taken 5417 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 487744 times.
|
487744 | assert(min_key ? range_start->n_fields > 0 : range_start->n_fields == 0); |
| 17915 | |||
| 17916 |
4/4✓ Branch 0 taken 409197 times.
✓ Branch 1 taken 78547 times.
✓ Branch 2 taken 409197 times.
✓ Branch 3 taken 78547 times.
|
896941 | row_sel_convert_mysql_key_to_innobase( |
| 17917 |
1/2✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
|
487744 | range_end, m_prebuilt->srch_key_val2, m_prebuilt->srch_key_val_len, index, |
| 17918 | (byte *)(max_key ? max_key->key : (const uchar *)nullptr), | ||
| 17919 | 409197 | (ulint)(max_key ? max_key->length : 0)); | |
| 17920 | |||
| 17921 |
3/4✓ Branch 0 taken 409197 times.
✓ Branch 1 taken 78547 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 487744 times.
|
487744 | assert(max_key ? range_end->n_fields > 0 : range_end->n_fields == 0); |
| 17922 | |||
| 17923 |
3/4✓ Branch 0 taken 482327 times.
✓ Branch 1 taken 5417 times.
✓ Branch 2 taken 487744 times.
✗ Branch 3 not taken.
|
487744 | mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag |
| 17924 | : HA_READ_KEY_EXACT); | ||
| 17925 | |||
| 17926 |
3/4✓ Branch 0 taken 409196 times.
✓ Branch 1 taken 78548 times.
✓ Branch 2 taken 487743 times.
✗ Branch 3 not taken.
|
487744 | mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag |
| 17927 | : HA_READ_KEY_EXACT); | ||
| 17928 | |||
| 17929 |
2/4✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 487744 times.
✗ Branch 3 not taken.
|
487743 | if (mode1 != PAGE_CUR_UNSUPP && mode2 != PAGE_CUR_UNSUPP) { |
| 17930 |
3/4✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 441 times.
✓ Branch 3 taken 487303 times.
|
487744 | if (dict_index_is_spatial(index)) { |
| 17931 | /*Only min_key used in spatial index. */ | ||
| 17932 |
1/2✓ Branch 0 taken 441 times.
✗ Branch 1 not taken.
|
441 | n_rows = rtr_estimate_n_rows_in_range(index, range_start, mode1); |
| 17933 | } else { | ||
| 17934 |
1/2✓ Branch 0 taken 487303 times.
✗ Branch 1 not taken.
|
487303 | n_rows = btr_estimate_n_rows_in_range(index, range_start, mode1, |
| 17935 | range_end, mode2); | ||
| 17936 | } | ||
| 17937 | } else { | ||
| 17938 | ✗ | n_rows = HA_POS_ERROR; | |
| 17939 | } | ||
| 17940 | |||
| 17941 |
1/2✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
|
487743 | mem_heap_free(heap); |
| 17942 | |||
| 17943 |
5/8✓ Branch 0 taken 487744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 487596 times.
✓ Branch 3 taken 148 times.
✓ Branch 4 taken 148 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 148 times.
✗ Branch 7 not taken.
|
487744 | DBUG_EXECUTE_IF( |
| 17944 | "print_btr_estimate_n_rows_in_range_return_value", | ||
| 17945 | push_warning_printf(ha_thd(), Sql_condition::SL_WARNING, ER_NO_DEFAULT, | ||
| 17946 | "btr_estimate_n_rows_in_range(): %" PRId64, n_rows);); | ||
| 17947 | |||
| 17948 | 487596 | func_exit: | |
| 17949 | |||
| 17950 | 487754 | m_prebuilt->trx->op_info = (char *)""; | |
| 17951 | |||
| 17952 | /* The MySQL optimizer seems to believe an estimate of 0 rows is | ||
| 17953 | always accurate and may return the result 'Empty set' based on that. | ||
| 17954 | The accuracy is not guaranteed, and even if it were, for a locking | ||
| 17955 | read we should anyway perform the search to set the next-key lock. | ||
| 17956 | Add 1 to the value to make sure MySQL does not make the assumption! */ | ||
| 17957 | |||
| 17958 |
2/2✓ Branch 0 taken 184023 times.
✓ Branch 1 taken 303731 times.
|
487754 | if (n_rows == 0) { |
| 17959 | 184023 | n_rows = 1; | |
| 17960 | } | ||
| 17961 | |||
| 17962 | 487754 | return (ha_rows)n_rows; | |
| 17963 | 487754 | } | |
| 17964 | |||
| 17965 | /** Gives an UPPER BOUND to the number of rows in a table. This is used in | ||
| 17966 | filesort.cc. | ||
| 17967 | @return upper bound of rows */ | ||
| 17968 | |||
| 17969 | 140233 | ha_rows ha_innobase::estimate_rows_upper_bound() { | |
| 17970 | const dict_index_t *index; | ||
| 17971 | ulonglong estimate; | ||
| 17972 | ulonglong local_data_file_length; | ||
| 17973 | |||
| 17974 |
1/2✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
|
140233 | DBUG_TRACE; |
| 17975 | |||
| 17976 | /* We do not know if MySQL can call this function before calling | ||
| 17977 | external_lock(). To be safe, update the thd of the current table | ||
| 17978 | handle. */ | ||
| 17979 | |||
| 17980 |
2/4✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 140233 times.
✗ Branch 3 not taken.
|
140233 | update_thd(ha_thd()); |
| 17981 | |||
| 17982 |
1/2✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
|
140233 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 17983 | |||
| 17984 | 140233 | m_prebuilt->trx->op_info = "calculating upper bound for table rows"; | |
| 17985 | |||
| 17986 |
1/2✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
|
140233 | index = m_prebuilt->table->first_index(); |
| 17987 | |||
| 17988 | 140233 | ulint stat_n_leaf_pages = index->stat_n_leaf_pages; | |
| 17989 | |||
| 17990 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 140233 times.
|
140233 | ut_a(stat_n_leaf_pages > 0); |
| 17991 | |||
| 17992 | 140233 | local_data_file_length = ((ulonglong)stat_n_leaf_pages) * UNIV_PAGE_SIZE; | |
| 17993 | |||
| 17994 | /* Calculate a minimum length for a clustered index record and from | ||
| 17995 | that an upper bound for the number of rows. Since we only calculate | ||
| 17996 | new statistics in row0mysql.cc when a table has grown by a threshold | ||
| 17997 | factor, we must add a safety factor 2 in front of the formula below. */ | ||
| 17998 | |||
| 17999 |
1/2✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
|
140233 | estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index); |
| 18000 | |||
| 18001 | 140233 | m_prebuilt->trx->op_info = ""; | |
| 18002 | |||
| 18003 | /* Set num_rows less than MERGEBUFF to simulate the case where we do | ||
| 18004 | not have enough space to merge the externally sorted file blocks. */ | ||
| 18005 |
2/6✓ Branch 0 taken 140233 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 140233 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
140233 | DBUG_EXECUTE_IF("set_num_rows_lt_MERGEBUFF", estimate = 2; |
| 18006 | DBUG_SET("-d,set_num_rows_lt_MERGEBUFF");); | ||
| 18007 | |||
| 18008 | 140233 | return (ha_rows)estimate; | |
| 18009 | 140233 | } | |
| 18010 | |||
| 18011 | /** How many seeks it will take to read through the table. This is to be | ||
| 18012 | comparable to the number returned by records_in_range so that we can | ||
| 18013 | decide if we should scan the table or use keys. | ||
| 18014 | @return estimated time measured in disk seeks */ | ||
| 18015 | |||
| 18016 | 79325649 | double ha_innobase::scan_time() { | |
| 18017 | /* Since MySQL seems to favor table scans too much over index | ||
| 18018 | searches, we pretend that a sequential read takes the same time | ||
| 18019 | as a random disk read, that is, we do not divide the following | ||
| 18020 | by 10, which would be physically realistic. */ | ||
| 18021 | |||
| 18022 | /* The locking below is disabled for performance reasons. Without | ||
| 18023 | it we could end up returning uninitialized value to the caller, | ||
| 18024 | which in the worst case could make some query plan go bogus or | ||
| 18025 | issue a Valgrind warning. */ | ||
| 18026 | |||
| 18027 |
2/2✓ Branch 0 taken 1429 times.
✓ Branch 1 taken 79324220 times.
|
79325649 | if (m_prebuilt == nullptr) { |
| 18028 | /* In case of derived table, Optimizer will try to fetch stat | ||
| 18029 | for table even before table is create or open. In such | ||
| 18030 | cases return default value of 1. | ||
| 18031 | TODO: This will be further improved to return some approximate | ||
| 18032 | estimate but that would also needs pre-population of stats | ||
| 18033 | structure. As of now approach is in sync with MyISAM. */ | ||
| 18034 | 1429 | return (ulonglong2double(stats.data_file_length) / IO_SIZE + 2); | |
| 18035 | } | ||
| 18036 | |||
| 18037 | ulint stat_clustered_index_size; | ||
| 18038 | |||
| 18039 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79324297 times.
|
79324220 | ut_a(m_prebuilt->table->stat_initialized); |
| 18040 | |||
| 18041 | 79324297 | stat_clustered_index_size = m_prebuilt->table->stat_clustered_index_size; | |
| 18042 | |||
| 18043 | 79324297 | return ((double)stat_clustered_index_size); | |
| 18044 | } | ||
| 18045 | |||
| 18046 | /** Calculate the time it takes to read a set of ranges through an index | ||
| 18047 | This enables us to optimise reads for clustered indexes. | ||
| 18048 | @return estimated time measured in disk seeks */ | ||
| 18049 | |||
| 18050 | 760552 | double ha_innobase::read_time( | |
| 18051 | uint index, /*!< in: key number */ | ||
| 18052 | uint ranges, /*!< in: how many ranges */ | ||
| 18053 | ha_rows rows) /*!< in: estimated number of rows in the ranges */ | ||
| 18054 | { | ||
| 18055 | ha_rows total_rows; | ||
| 18056 | |||
| 18057 |
2/2✓ Branch 0 taken 356817 times.
✓ Branch 1 taken 403735 times.
|
760552 | if (index != table->s->primary_key) { |
| 18058 | /* Not clustered */ | ||
| 18059 | 356817 | return (handler::read_time(index, ranges, rows)); | |
| 18060 | } | ||
| 18061 | |||
| 18062 |
2/2✓ Branch 0 taken 262922 times.
✓ Branch 1 taken 140813 times.
|
403735 | if (rows <= 2) { |
| 18063 | 262922 | return ((double)rows); | |
| 18064 | } | ||
| 18065 | |||
| 18066 | /* Assume that the read time is proportional to the scan time for all | ||
| 18067 | rows + at most one seek per range. */ | ||
| 18068 | |||
| 18069 | 140813 | double time_for_scan = scan_time(); | |
| 18070 | |||
| 18071 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 140836 times.
|
140837 | if ((total_rows = estimate_rows_upper_bound()) < rows) { |
| 18072 | 1 | return (time_for_scan); | |
| 18073 | } | ||
| 18074 | |||
| 18075 | 140836 | return (ranges + (double)rows / (double)total_rows * time_for_scan); | |
| 18076 | } | ||
| 18077 | |||
| 18078 | /** Return the size of the InnoDB memory buffer. */ | ||
| 18079 | |||
| 18080 | 2091035 | longlong ha_innobase::get_memory_buffer_size() const { | |
| 18081 | 2091035 | return (srv_buf_pool_curr_size); | |
| 18082 | } | ||
| 18083 | |||
| 18084 | /** Update the system variable with the given value of the InnoDB | ||
| 18085 | buffer pool size. | ||
| 18086 | @param[in] buf_pool_size given value of buffer pool size.*/ | ||
| 18087 | 23 | void innodb_set_buf_pool_size(long long buf_pool_size) { | |
| 18088 | 23 | srv_buf_pool_curr_size = buf_pool_size; | |
| 18089 | 23 | } | |
| 18090 | |||
| 18091 | /** Calculates the key number used inside MySQL for an Innobase index. We | ||
| 18092 | will first check the "index translation table" for a match of the index to | ||
| 18093 | get the index number. If there does not exist an "index translation table", | ||
| 18094 | or not able to find the index in the translation table, then we will fall | ||
| 18095 | back to the traditional way of looping through dict_index_t list to find a | ||
| 18096 | match. In this case, we have to take into account if we generated a | ||
| 18097 | default clustered index for the table | ||
| 18098 | @return the key number used inside MySQL */ | ||
| 18099 | 488670 | static int innobase_get_mysql_key_number_for_index( | |
| 18100 | INNOBASE_SHARE *share, /*!< in: share structure for index | ||
| 18101 | translation table. */ | ||
| 18102 | const TABLE *table, /*!< in: table in MySQL data | ||
| 18103 | dictionary */ | ||
| 18104 | dict_table_t *ib_table, /*!< in: table in InnoDB data | ||
| 18105 | dictionary */ | ||
| 18106 | const dict_index_t *index) /*!< in: index */ | ||
| 18107 | { | ||
| 18108 | const dict_index_t *ind; | ||
| 18109 | unsigned int i; | ||
| 18110 | |||
| 18111 | /* If index does not belong to the table object of share structure | ||
| 18112 | (ib_table comes from the share structure) search the index->table | ||
| 18113 | object instead */ | ||
| 18114 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 488670 times.
|
488670 | if (index->table != ib_table) { |
| 18115 | ✗ | i = 0; | |
| 18116 | ✗ | ind = index->table->first_index(); | |
| 18117 | |||
| 18118 | ✗ | while (index != ind) { | |
| 18119 | ✗ | ind = ind->next(); | |
| 18120 | ✗ | i++; | |
| 18121 | } | ||
| 18122 | |||
| 18123 | ✗ | if (row_table_got_default_clust_index(index->table)) { | |
| 18124 | ✗ | ut_a(i > 0); | |
| 18125 | ✗ | i--; | |
| 18126 | } | ||
| 18127 | |||
| 18128 | ✗ | return (i); | |
| 18129 | } | ||
| 18130 | |||
| 18131 | /* If index translation table exists, we will first check | ||
| 18132 | the index through index translation table for a match. */ | ||
| 18133 |
1/2✓ Branch 0 taken 488670 times.
✗ Branch 1 not taken.
|
488670 | if (share->idx_trans_tbl.index_mapping != nullptr) { |
| 18134 |
1/2✓ Branch 0 taken 488870 times.
✗ Branch 1 not taken.
|
488870 | for (i = 0; i < share->idx_trans_tbl.index_count; i++) { |
| 18135 |
2/2✓ Branch 0 taken 488670 times.
✓ Branch 1 taken 200 times.
|
488870 | if (share->idx_trans_tbl.index_mapping[i] == index) { |
| 18136 | 488670 | return (i); | |
| 18137 | } | ||
| 18138 | } | ||
| 18139 | |||
| 18140 | /* Print an error message if we cannot find the index | ||
| 18141 | in the "index translation table". */ | ||
| 18142 | ✗ | if (index->is_committed()) { | |
| 18143 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_FAILED_TO_FIND_IDX, index->name()); | |
| 18144 | } | ||
| 18145 | } | ||
| 18146 | |||
| 18147 | /* If we do not have an "index translation table", or not able | ||
| 18148 | to find the index in the translation table, we'll directly find | ||
| 18149 | matching index with information from mysql TABLE structure and | ||
| 18150 | InnoDB dict_index_t list */ | ||
| 18151 | ✗ | for (i = 0; i < table->s->keys; i++) { | |
| 18152 | ✗ | ind = dict_table_get_index_on_name(ib_table, table->key_info[i].name); | |
| 18153 | |||
| 18154 | ✗ | if (index == ind) { | |
| 18155 | ✗ | return (i); | |
| 18156 | } | ||
| 18157 | } | ||
| 18158 | |||
| 18159 | /* Loop through each index of the table and lock them */ | ||
| 18160 | ✗ | for (ind = ib_table->first_index(); ind != nullptr; ind = ind->next()) { | |
| 18161 | ✗ | if (index == ind) { | |
| 18162 | /* Temp index is internal to InnoDB, that is | ||
| 18163 | not present in the MySQL index list, so no | ||
| 18164 | need to print such mismatch warning. */ | ||
| 18165 | ✗ | if (index->is_committed()) { | |
| 18166 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_INTERNAL_INDEX, index->name()); | |
| 18167 | } | ||
| 18168 | ✗ | return (-1); | |
| 18169 | } | ||
| 18170 | } | ||
| 18171 | |||
| 18172 | ✗ | ut_error; | |
| 18173 | } | ||
| 18174 | |||
| 18175 | /** Calculate Record Per Key value. | ||
| 18176 | Need to exclude the NULL value if innodb_stats_method is set to "nulls_ignored" | ||
| 18177 | @param[in] index InnoDB index. | ||
| 18178 | @param[in] i The column we are calculating rec per key. | ||
| 18179 | @param[in] records Estimated total records. | ||
| 18180 | @return estimated record per key value */ | ||
| 18181 | 48242139 | rec_per_key_t innodb_rec_per_key(const dict_index_t *index, ulint i, | |
| 18182 | ha_rows records) { | ||
| 18183 | rec_per_key_t rec_per_key; | ||
| 18184 | uint64_t n_diff; | ||
| 18185 | |||
| 18186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48242148 times.
|
48242139 | ut_a(index->table->stat_initialized); |
| 18187 | |||
| 18188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48242143 times.
|
48242148 | ut_ad(i < dict_index_get_n_unique(index)); |
| 18189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48242161 times.
|
48242143 | ut_ad(!dict_index_is_spatial(index)); |
| 18190 | |||
| 18191 |
2/2✓ Branch 0 taken 6376617 times.
✓ Branch 1 taken 41865544 times.
|
48242161 | if (records == 0) { |
| 18192 | /* "Records per key" is meaningless for empty tables. | ||
| 18193 | Return 1.0 because that is most convenient to the Optimizer. */ | ||
| 18194 | 6376617 | return (1.0); | |
| 18195 | } | ||
| 18196 | |||
| 18197 | 41865544 | n_diff = index->stat_n_diff_key_vals[i]; | |
| 18198 | |||
| 18199 |
2/2✓ Branch 0 taken 6601355 times.
✓ Branch 1 taken 35264189 times.
|
41865544 | if (n_diff == 0) { |
| 18200 | 6601355 | rec_per_key = static_cast<rec_per_key_t>(records); | |
| 18201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35264189 times.
|
35264189 | } else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) { |
| 18202 | uint64_t n_null; | ||
| 18203 | uint64_t n_non_null; | ||
| 18204 | |||
| 18205 | ✗ | n_non_null = index->stat_n_non_null_key_vals[i]; | |
| 18206 | |||
| 18207 | /* In theory, index->stat_n_non_null_key_vals[i] | ||
| 18208 | should always be less than the number of records. | ||
| 18209 | Since this is statistics value, the value could | ||
| 18210 | have slight discrepancy. But we will make sure | ||
| 18211 | the number of null values is not a negative number. */ | ||
| 18212 | ✗ | if (records < n_non_null) { | |
| 18213 | ✗ | n_null = 0; | |
| 18214 | } else { | ||
| 18215 | ✗ | n_null = records - n_non_null; | |
| 18216 | } | ||
| 18217 | |||
| 18218 | /* If the number of NULL values is the same as or | ||
| 18219 | large than that of the distinct values, we could | ||
| 18220 | consider that the table consists mostly of NULL value. | ||
| 18221 | Set rec_per_key to 1. */ | ||
| 18222 | ✗ | if (n_diff <= n_null) { | |
| 18223 | ✗ | rec_per_key = 1.0; | |
| 18224 | } else { | ||
| 18225 | /* Need to exclude rows with NULL values from | ||
| 18226 | rec_per_key calculation */ | ||
| 18227 | ✗ | rec_per_key = | |
| 18228 | ✗ | static_cast<rec_per_key_t>(records - n_null) / (n_diff - n_null); | |
| 18229 | } | ||
| 18230 | } else { | ||
| 18231 | #ifdef UNIV_DEBUG | ||
| 18232 |
2/2✓ Branch 0 taken 4457235 times.
✓ Branch 1 taken 30806954 times.
|
35264189 | if (!index->table->is_dd_table) { |
| 18233 |
2/2✓ Branch 0 taken 4445033 times.
✓ Branch 1 taken 12202 times.
|
4457235 | DEBUG_SYNC_C("after_checking_for_0"); |
| 18234 | } | ||
| 18235 | #endif /* UNIV_DEBUG */ | ||
| 18236 | 35264202 | rec_per_key = static_cast<rec_per_key_t>(records) / n_diff; | |
| 18237 | } | ||
| 18238 | |||
| 18239 |
2/2✓ Branch 0 taken 3115049 times.
✓ Branch 1 taken 38750508 times.
|
41865557 | if (rec_per_key < 1.0) { |
| 18240 | /* Values below 1.0 are meaningless and must be due to the | ||
| 18241 | stats being imprecise. */ | ||
| 18242 | 3115049 | rec_per_key = 1.0; | |
| 18243 | } | ||
| 18244 | |||
| 18245 | 41865557 | return (rec_per_key); | |
| 18246 | } | ||
| 18247 | |||
| 18248 | /** Read the auto_increment counter of a table, using the AUTOINC lock | ||
| 18249 | irrespective of innodb_autoinc_lock_mode. | ||
| 18250 | @param[in,out] innodb_table InnoDB table object | ||
| 18251 | @param[in] print_note Print note if not an I_S query. | ||
| 18252 | @return the autoinc value */ | ||
| 18253 | 16591 | static ulonglong innobase_peek_autoinc(dict_table_t *innodb_table, | |
| 18254 | bool print_note) { | ||
| 18255 | ulonglong auto_inc; | ||
| 18256 | |||
| 18257 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16591 times.
|
16591 | ut_a(innodb_table != nullptr); |
| 18258 | |||
| 18259 | 16591 | dict_table_autoinc_lock(innodb_table); | |
| 18260 | |||
| 18261 | 16591 | auto_inc = dict_table_autoinc_read(innodb_table); | |
| 18262 | |||
| 18263 |
3/4✓ Branch 0 taken 3071 times.
✓ Branch 1 taken 13520 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3071 times.
|
16591 | if (auto_inc == 0 && print_note) { |
| 18264 | ✗ | ib::info(ER_IB_MSG_569) << "AUTOINC next value generation is disabled for " | |
| 18265 | ✗ | << innodb_table->name; | |
| 18266 | } | ||
| 18267 | |||
| 18268 | 16591 | dict_table_autoinc_unlock(innodb_table); | |
| 18269 | |||
| 18270 | 16591 | return (auto_inc); | |
| 18271 | } | ||
| 18272 | |||
| 18273 | /** Calculate delete length statistic. | ||
| 18274 | @param[in] ib_table table object | ||
| 18275 | @param[in,out] stats stats structure to hold calculated values | ||
| 18276 | @param[in,out] thd user thread handle (for issuing warnings) */ | ||
| 18277 | 10570 | static void calculate_delete_length_stat(const dict_table_t *ib_table, | |
| 18278 | ha_statistics *stats, THD *thd) { | ||
| 18279 | uintmax_t avail_space; | ||
| 18280 | |||
| 18281 | 10570 | avail_space = fsp_get_available_space_in_free_extents(ib_table->space); | |
| 18282 | |||
| 18283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10570 times.
|
10570 | if (avail_space == UINTMAX_MAX) { |
| 18284 | char errbuf[MYSYS_STRERROR_SIZE]; | ||
| 18285 | ✗ | std::ostringstream err_msg; | |
| 18286 | ✗ | err_msg << "InnoDB: Trying to get the free space for table " | |
| 18287 | ✗ | << ib_table->name | |
| 18288 | << " but its tablespace has been" | ||
| 18289 | " discarded or the .ibd file is missing. Setting" | ||
| 18290 | ✗ | " the free space to zero. (errno: " | |
| 18291 | ✗ | << errno << " - " << my_strerror(errbuf, sizeof(errbuf), errno) | |
| 18292 | ✗ | << ")"; | |
| 18293 | |||
| 18294 | ✗ | push_warning(thd, Sql_condition::SL_WARNING, ER_CANT_GET_STAT, | |
| 18295 | ✗ | err_msg.str().c_str()); | |
| 18296 | |||
| 18297 | ✗ | stats->delete_length = 0; | |
| 18298 | ✗ | } else { | |
| 18299 | 10570 | stats->delete_length = avail_space * 1024; | |
| 18300 | } | ||
| 18301 | 10570 | } | |
| 18302 | |||
| 18303 | /** Calculate stats based on index size. | ||
| 18304 | @param[in] ib_table table object | ||
| 18305 | @param[in] n_rows number of rows | ||
| 18306 | @param[in] stat_clustered_index_size clustered index size | ||
| 18307 | @param[in] stat_sum_of_other_index_sizes sum of non-clustered index sizes | ||
| 18308 | @param[in,out] stats the stats structure to hold | ||
| 18309 | calculated values */ | ||
| 18310 | 8698707 | static void calculate_index_size_stats(const dict_table_t *ib_table, | |
| 18311 | uint64_t n_rows, | ||
| 18312 | ulint stat_clustered_index_size, | ||
| 18313 | ulint stat_sum_of_other_index_sizes, | ||
| 18314 | ha_statistics *stats) { | ||
| 18315 |
1/2✓ Branch 0 taken 8698745 times.
✗ Branch 1 not taken.
|
8698707 | const page_size_t &page_size = dict_table_page_size(ib_table); |
| 18316 | |||
| 18317 | 8698745 | stats->records = static_cast<ha_rows>(n_rows); | |
| 18318 | 8698762 | stats->data_file_length = | |
| 18319 |
1/2✓ Branch 0 taken 8698762 times.
✗ Branch 1 not taken.
|
8698745 | static_cast<ulonglong>(stat_clustered_index_size) * page_size.physical(); |
| 18320 | 8698802 | stats->index_file_length = | |
| 18321 | 8698802 | static_cast<ulonglong>(stat_sum_of_other_index_sizes) * | |
| 18322 |
1/2✓ Branch 0 taken 8698802 times.
✗ Branch 1 not taken.
|
8698762 | page_size.physical(); |
| 18323 |
2/2✓ Branch 0 taken 530952 times.
✓ Branch 1 taken 8167850 times.
|
8698802 | if (stats->records == 0) { |
| 18324 | 530952 | stats->mean_rec_length = 0; | |
| 18325 | } else { | ||
| 18326 | 8167850 | stats->mean_rec_length = | |
| 18327 | 8167850 | static_cast<ulong>(stats->data_file_length / stats->records); | |
| 18328 | } | ||
| 18329 | 8698802 | } | |
| 18330 | |||
| 18331 | /** Estimate what percentage of an index's pages are cached in the buffer pool | ||
| 18332 | @param[in] index index whose pages to look up | ||
| 18333 | @return a real number in [0.0, 1.0] designating the percentage of cached pages | ||
| 18334 | */ | ||
| 18335 | 23843449 | inline double index_pct_cached(const dict_index_t *index) { | |
| 18336 | 23843449 | const ulint n_leaf = index->stat_n_leaf_pages; | |
| 18337 | |||
| 18338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23843449 times.
|
23843449 | if (n_leaf == 0) { |
| 18339 | ✗ | return (0.0); | |
| 18340 | } | ||
| 18341 | |||
| 18342 | const uint64_t n_in_mem = | ||
| 18343 |
1/2✓ Branch 0 taken 23843511 times.
✗ Branch 1 not taken.
|
23843449 | buf_stat_per_index->get(index_id_t(index->space, index->id)); |
| 18344 | |||
| 18345 | 23843511 | const double ratio = static_cast<double>(n_in_mem) / n_leaf; | |
| 18346 | |||
| 18347 | 23843511 | return (std::max(std::min(ratio, 1.0), 0.0)); | |
| 18348 | } | ||
| 18349 | |||
| 18350 | /** Returns statistics information of the table to the MySQL interpreter, in | ||
| 18351 | various fields of the handle object. | ||
| 18352 | @param[in] flag what information is requested | ||
| 18353 | @param[in] is_analyze True if called from "::analyze()". | ||
| 18354 | @return HA_ERR_* error code or 0 */ | ||
| 18355 | 9289488 | int ha_innobase::info_low(uint flag, bool is_analyze) { | |
| 18356 | dict_table_t *ib_table; | ||
| 18357 | uint64_t n_rows; | ||
| 18358 | |||
| 18359 |
1/2✓ Branch 0 taken 9289603 times.
✗ Branch 1 not taken.
|
9289488 | DBUG_TRACE; |
| 18360 | |||
| 18361 |
3/4✓ Branch 0 taken 9157907 times.
✓ Branch 1 taken 131696 times.
✓ Branch 2 taken 9157934 times.
✗ Branch 3 not taken.
|
9289603 | DEBUG_SYNC_C("ha_innobase_info_low"); |
| 18362 | |||
| 18363 | /* If we are forcing recovery at a high level, we will suppress | ||
| 18364 | statistics calculation on tables, because that may crash the | ||
| 18365 | server if an index is badly corrupted. */ | ||
| 18366 | |||
| 18367 | /* We do not know if MySQL can call this function before calling | ||
| 18368 | external_lock(). To be safe, update the thd of the current table | ||
| 18369 | handle. */ | ||
| 18370 | |||
| 18371 |
2/4✓ Branch 0 taken 9289612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9289606 times.
✗ Branch 3 not taken.
|
9289630 | update_thd(ha_thd()); |
| 18372 | |||
| 18373 | 9289606 | m_prebuilt->trx->op_info = (char *)"returning various info to MySQL"; | |
| 18374 | |||
| 18375 | 9289606 | ib_table = m_prebuilt->table; | |
| 18376 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9289601 times.
|
9289606 | assert(ib_table->n_ref_count > 0); |
| 18377 | |||
| 18378 |
2/2✓ Branch 0 taken 132854 times.
✓ Branch 1 taken 9156747 times.
|
9289601 | if (flag & HA_STATUS_TIME) { |
| 18379 |
4/4✓ Branch 0 taken 127330 times.
✓ Branch 1 taken 5524 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 127258 times.
|
132854 | if (is_analyze || innobase_stats_on_metadata) { |
| 18380 | dict_stats_upd_option_t opt; | ||
| 18381 | dberr_t ret; | ||
| 18382 | |||
| 18383 | 5596 | m_prebuilt->trx->op_info = "updating table statistics"; | |
| 18384 | |||
| 18385 |
3/4✓ Branch 0 taken 5596 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5404 times.
✓ Branch 3 taken 192 times.
|
5596 | if (dict_stats_is_persistent_enabled(ib_table)) { |
| 18386 |
2/2✓ Branch 0 taken 5332 times.
✓ Branch 1 taken 72 times.
|
5404 | if (is_analyze) { |
| 18387 | /* If this table is already queued for background analyze, remove it | ||
| 18388 | from the queue as we are about to do the same */ | ||
| 18389 |
2/2✓ Branch 0 taken 5329 times.
✓ Branch 1 taken 3 times.
|
5332 | if (!srv_read_only_mode) { |
| 18390 |
1/2✓ Branch 0 taken 5329 times.
✗ Branch 1 not taken.
|
5329 | dict_mutex_enter_for_mysql(); |
| 18391 |
1/2✓ Branch 0 taken 5329 times.
✗ Branch 1 not taken.
|
5329 | dict_stats_recalc_pool_del(ib_table); |
| 18392 |
1/2✓ Branch 0 taken 5329 times.
✗ Branch 1 not taken.
|
5329 | dict_mutex_exit_for_mysql(); |
| 18393 | } | ||
| 18394 | 5332 | opt = DICT_STATS_RECALC_PERSISTENT; | |
| 18395 | } else { | ||
| 18396 | /* This is e.g. 'SHOW INDEXES', fetch | ||
| 18397 | the persistent stats from disk. */ | ||
| 18398 | 72 | opt = DICT_STATS_FETCH_ONLY_IF_NOT_IN_MEMORY; | |
| 18399 | } | ||
| 18400 | } else { | ||
| 18401 | 192 | opt = DICT_STATS_RECALC_TRANSIENT; | |
| 18402 | } | ||
| 18403 | |||
| 18404 |
2/4✓ Branch 0 taken 5596 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5596 times.
|
5596 | ut_ad(!dict_sys_mutex_own()); |
| 18405 |
1/2✓ Branch 0 taken 5596 times.
✗ Branch 1 not taken.
|
5596 | ret = dict_stats_update(ib_table, opt); |
| 18406 | |||
| 18407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5596 times.
|
5596 | if (ret != DB_SUCCESS) { |
| 18408 | ✗ | m_prebuilt->trx->op_info = ""; | |
| 18409 | ✗ | return HA_ERR_GENERIC; | |
| 18410 | } | ||
| 18411 | |||
| 18412 | 5596 | m_prebuilt->trx->op_info = "returning various info to MySQL"; | |
| 18413 | } | ||
| 18414 | |||
| 18415 | 132854 | stats.update_time = (ulong)std::chrono::system_clock::to_time_t( | |
| 18416 | 265708 | ib_table->update_time.load()); | |
| 18417 | } | ||
| 18418 | |||
| 18419 |
2/2✓ Branch 0 taken 8695253 times.
✓ Branch 1 taken 594348 times.
|
9289601 | if (flag & HA_STATUS_VARIABLE) { |
| 18420 | ulint stat_clustered_index_size; | ||
| 18421 | ulint stat_sum_of_other_index_sizes; | ||
| 18422 | |||
| 18423 |
2/2✓ Branch 0 taken 19842 times.
✓ Branch 1 taken 8675411 times.
|
8695253 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 18424 |
1/2✓ Branch 0 taken 19842 times.
✗ Branch 1 not taken.
|
19842 | dict_table_stats_lock(ib_table, RW_S_LATCH); |
| 18425 | } | ||
| 18426 | |||
| 18427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8695231 times.
|
8695253 | ut_a(ib_table->stat_initialized); |
| 18428 | |||
| 18429 | 8695231 | n_rows = ib_table->stat_n_rows; | |
| 18430 | |||
| 18431 | 8695231 | stat_clustered_index_size = ib_table->stat_clustered_index_size; | |
| 18432 | |||
| 18433 | 8695231 | stat_sum_of_other_index_sizes = ib_table->stat_sum_of_other_index_sizes; | |
| 18434 | |||
| 18435 |
2/2✓ Branch 0 taken 19842 times.
✓ Branch 1 taken 8675389 times.
|
8695231 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 18436 |
1/2✓ Branch 0 taken 19842 times.
✗ Branch 1 not taken.
|
19842 | dict_table_stats_unlock(ib_table, RW_S_LATCH); |
| 18437 | } | ||
| 18438 | |||
| 18439 | /* | ||
| 18440 | The MySQL optimizer seems to assume in a left join that n_rows | ||
| 18441 | is an accurate estimate if it is zero. Of course, it is not, | ||
| 18442 | since we do not have any locks on the rows yet at this phase. | ||
| 18443 | Since SHOW TABLE STATUS seems to call this function with the | ||
| 18444 | HA_STATUS_TIME flag set, while the left join optimizer does not | ||
| 18445 | set that flag, we add one to a zero value if the flag is not | ||
| 18446 | set. That way SHOW TABLE STATUS will show the best estimate, | ||
| 18447 | while the optimizer never sees the table empty. | ||
| 18448 | However, if it is internal temporary table used by optimizer, | ||
| 18449 | the count should be accurate */ | ||
| 18450 | |||
| 18451 |
4/4✓ Branch 0 taken 2403358 times.
✓ Branch 1 taken 6291873 times.
✓ Branch 2 taken 2282024 times.
✓ Branch 3 taken 121334 times.
|
8695231 | if (n_rows == 0 && !(flag & HA_STATUS_TIME) && |
| 18452 |
2/2✓ Branch 0 taken 1873949 times.
✓ Branch 1 taken 408075 times.
|
2282024 | table_share->table_category != TABLE_CATEGORY_TEMPORARY) { |
| 18453 | 1873949 | n_rows++; | |
| 18454 | } | ||
| 18455 | |||
| 18456 | 8695231 | stats.records = (ha_rows)n_rows; | |
| 18457 | 8695231 | stats.deleted = 0; | |
| 18458 | |||
| 18459 |
1/2✓ Branch 0 taken 8695299 times.
✗ Branch 1 not taken.
|
8695231 | calculate_index_size_stats(ib_table, n_rows, stat_clustered_index_size, |
| 18460 | stat_sum_of_other_index_sizes, &stats); | ||
| 18461 | |||
| 18462 | /* Since fsp_get_available_space_in_free_extents() is | ||
| 18463 | acquiring latches inside InnoDB, we do not call it if we | ||
| 18464 | are asked by MySQL to avoid locking. Another reason to | ||
| 18465 | avoid the call is that it uses quite a lot of CPU. | ||
| 18466 | See Bug#38185. */ | ||
| 18467 |
4/4✓ Branch 0 taken 19842 times.
✓ Branch 1 taken 8675457 times.
✓ Branch 2 taken 7069 times.
✓ Branch 3 taken 12773 times.
|
8695299 | if (flag & HA_STATUS_NO_LOCK || !(flag & HA_STATUS_VARIABLE_EXTRA)) { |
| 18468 | /* We do not update delete_length if no | ||
| 18469 | locking is requested so the "old" value can | ||
| 18470 | remain. delete_length is initialized to 0 in | ||
| 18471 | the ha_statistics' constructor. Also we only | ||
| 18472 | need delete_length to be set when | ||
| 18473 | HA_STATUS_VARIABLE_EXTRA is set */ | ||
| 18474 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7069 times.
|
7069 | } else if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { |
| 18475 | /* Avoid accessing the tablespace if | ||
| 18476 | innodb_crash_recovery is set to a high value. */ | ||
| 18477 | ✗ | stats.delete_length = 0; | |
| 18478 | } else { | ||
| 18479 |
2/4✓ Branch 0 taken 7069 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7043 times.
✗ Branch 3 not taken.
|
7069 | calculate_delete_length_stat(ib_table, &stats, ha_thd()); |
| 18480 | } | ||
| 18481 | |||
| 18482 | 8695273 | stats.check_time = 0; | |
| 18483 | 8695273 | stats.mrr_length_per_rec = ref_length + sizeof(void *); | |
| 18484 | } | ||
| 18485 | |||
| 18486 | /* Verify the number of indexes in InnoDB and MySQL | ||
| 18487 | matches up. If m_prebuilt->clust_index_was_generated | ||
| 18488 | holds, InnoDB defines GEN_CLUST_INDEX internally. */ | ||
| 18489 |
1/2✓ Branch 0 taken 9289536 times.
✗ Branch 1 not taken.
|
9289621 | ulint num_innodb_index = UT_LIST_GET_LEN(ib_table->indexes) - |
| 18490 | 9289536 | m_prebuilt->clust_index_was_generated; | |
| 18491 |
2/2✓ Branch 0 taken 6171 times.
✓ Branch 1 taken 9283365 times.
|
9289536 | if (table->s->keys < num_innodb_index) { |
| 18492 | /* If there are too many indexes defined | ||
| 18493 | inside InnoDB, ignore those that are being | ||
| 18494 | created, because MySQL will only consider | ||
| 18495 | the fully built indexes here. */ | ||
| 18496 | |||
| 18497 |
6/10✓ Branch 0 taken 6171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6171 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28783 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34954 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 28783 times.
✓ Branch 9 taken 6171 times.
|
34954 | for (const dict_index_t *index : ib_table->indexes) { |
| 18498 | /* First, online index creation is | ||
| 18499 | completed inside InnoDB, and then | ||
| 18500 | MySQL attempts to upgrade the | ||
| 18501 | meta-data lock so that it can rebuild | ||
| 18502 | the .frm file. If we get here in that | ||
| 18503 | time frame, dict_index_is_online_ddl() | ||
| 18504 | would not hold and the index would | ||
| 18505 | still not be included in TABLE_SHARE. */ | ||
| 18506 |
3/4✓ Branch 0 taken 28783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 279 times.
✓ Branch 3 taken 28504 times.
|
28783 | if (!index->is_committed()) { |
| 18507 | 279 | num_innodb_index--; | |
| 18508 | } | ||
| 18509 | } | ||
| 18510 | |||
| 18511 |
4/4✓ Branch 0 taken 5901 times.
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 5901 times.
✓ Branch 3 taken 270 times.
|
12072 | if (table->s->keys < num_innodb_index && |
| 18512 |
2/4✓ Branch 0 taken 5901 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5901 times.
✗ Branch 3 not taken.
|
5901 | innobase_fts_check_doc_id_index(ib_table, nullptr, nullptr) == |
| 18513 | FTS_EXIST_DOC_ID_INDEX) { | ||
| 18514 | 5901 | num_innodb_index--; | |
| 18515 | } | ||
| 18516 | } | ||
| 18517 | |||
| 18518 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9289536 times.
|
9289536 | if (table->s->keys != num_innodb_index) { |
| 18519 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_MORE_THAN_DEFINED_IN_MYSQL, | |
| 18520 | ib_table->name.m_name, num_innodb_index, table->s->keys); | ||
| 18521 | } | ||
| 18522 | |||
| 18523 |
2/2✓ Branch 0 taken 125423 times.
✓ Branch 1 taken 9164113 times.
|
9289536 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 18524 |
1/2✓ Branch 0 taken 125423 times.
✗ Branch 1 not taken.
|
125423 | dict_table_stats_lock(ib_table, RW_S_LATCH); |
| 18525 | } | ||
| 18526 | |||
| 18527 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9289532 times.
|
9289536 | ut_a(ib_table->stat_initialized); |
| 18528 | |||
| 18529 | 9289532 | const dict_index_t *pk = UT_LIST_GET_FIRST(ib_table->indexes); | |
| 18530 | |||
| 18531 |
2/2✓ Branch 0 taken 23914680 times.
✓ Branch 1 taken 9289630 times.
|
33204310 | for (uint i = 0; i < table->s->keys; i++) { |
| 18532 | ulong j; | ||
| 18533 | /* We could get index quickly through internal | ||
| 18534 | index mapping with the index translation table. | ||
| 18535 | The identity of index (match up index name with | ||
| 18536 | that of table->key_info[i]) is already verified in | ||
| 18537 | innobase_get_index(). */ | ||
| 18538 |
1/2✓ Branch 0 taken 23914823 times.
✗ Branch 1 not taken.
|
23914680 | dict_index_t *index = innobase_get_index(i); |
| 18539 | |||
| 18540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23914823 times.
|
23914823 | if (index == nullptr) { |
| 18541 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_IDX_CNT_FEWER_THAN_DEFINED_IN_MYSQL, | |
| 18542 | ib_table->name.m_name, TROUBLESHOOTING_MSG); | ||
| 18543 | ✗ | break; | |
| 18544 | } | ||
| 18545 | |||
| 18546 | 23914823 | KEY *key = &table->key_info[i]; | |
| 18547 | |||
| 18548 | double pct_cached; | ||
| 18549 | |||
| 18550 | /* We do not maintain stats for fulltext or spatial indexes. | ||
| 18551 | Thus, we can't calculate pct_cached below because we need | ||
| 18552 | dict_index_t::stat_n_leaf_pages for that. See | ||
| 18553 | dict_stats_should_ignore_index(). */ | ||
| 18554 |
4/4✓ Branch 0 taken 23898963 times.
✓ Branch 1 taken 15860 times.
✓ Branch 2 taken 55467 times.
✓ Branch 3 taken 23843496 times.
|
23914823 | if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) { |
| 18555 | 71327 | pct_cached = IN_MEMORY_ESTIMATE_UNKNOWN; | |
| 18556 | } else { | ||
| 18557 |
1/2✓ Branch 0 taken 23843421 times.
✗ Branch 1 not taken.
|
23843496 | pct_cached = index_pct_cached(index); |
| 18558 | } | ||
| 18559 | |||
| 18560 | 23914748 | key->set_in_memory_estimate(pct_cached); | |
| 18561 | |||
| 18562 |
2/2✓ Branch 0 taken 7775709 times.
✓ Branch 1 taken 16139083 times.
|
23914792 | if (index == pk) { |
| 18563 | 7775709 | stats.table_in_mem_estimate = pct_cached; | |
| 18564 | } | ||
| 18565 | |||
| 18566 |
2/2✓ Branch 0 taken 11604058 times.
✓ Branch 1 taken 12310734 times.
|
23914792 | if (flag & HA_STATUS_CONST) { |
| 18567 |
2/2✓ Branch 0 taken 3051 times.
✓ Branch 1 taken 11601005 times.
|
11604058 | if (!key->supports_records_per_key()) { |
| 18568 | 3051 | continue; | |
| 18569 | } | ||
| 18570 | |||
| 18571 |
2/2✓ Branch 0 taken 24124187 times.
✓ Branch 1 taken 11600993 times.
|
35725180 | for (j = 0; j < key->actual_key_parts; j++) { |
| 18572 |
4/4✓ Branch 0 taken 24118965 times.
✓ Branch 1 taken 5222 times.
✓ Branch 2 taken 4140 times.
✓ Branch 3 taken 24114825 times.
|
24124187 | if ((key->flags & HA_FULLTEXT) || (key->flags & HA_SPATIAL)) { |
| 18573 | /* The record per key does not apply to | ||
| 18574 | FTS or Spatial indexes. */ | ||
| 18575 | 9362 | key->set_records_per_key(j, 1.0f); | |
| 18576 | 9367 | continue; | |
| 18577 | } | ||
| 18578 | |||
| 18579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24114825 times.
|
24114825 | if (j + 1 > index->n_uniq) { |
| 18580 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_IDX_COLUMN_CNT_DIFF, index->name(), | |
| 18581 | ib_table->name.m_name, (unsigned long)index->n_uniq, j + 1, | ||
| 18582 | TROUBLESHOOTING_MSG); | ||
| 18583 | ✗ | break; | |
| 18584 | } | ||
| 18585 | |||
| 18586 | /* innodb_rec_per_key() will use | ||
| 18587 | index->stat_n_diff_key_vals[] and the value we | ||
| 18588 | pass index->table->stat_n_rows. Both are | ||
| 18589 | calculated by ANALYZE and by the background | ||
| 18590 | stats gathering thread (which kicks in when too | ||
| 18591 | much of the table has been changed). In | ||
| 18592 | addition table->stat_n_rows is adjusted with | ||
| 18593 | each DML (e.g. ++ on row insert). Those | ||
| 18594 | adjustments are not MVCC'ed and not even | ||
| 18595 | reversed on rollback. So, | ||
| 18596 | index->stat_n_diff_key_vals[] and | ||
| 18597 | index->table->stat_n_rows could have been | ||
| 18598 | calculated at different time. This is | ||
| 18599 | acceptable. */ | ||
| 18600 | const rec_per_key_t rec_per_key = | ||
| 18601 |
1/2✓ Branch 0 taken 24114803 times.
✗ Branch 1 not taken.
|
24114825 | innodb_rec_per_key(index, (ulint)j, index->table->stat_n_rows); |
| 18602 | |||
| 18603 | 24114803 | key->set_records_per_key(j, rec_per_key); | |
| 18604 | |||
| 18605 | /* The code below is legacy and should be | ||
| 18606 | removed together with this comment once we | ||
| 18607 | are sure the new floating point rec_per_key, | ||
| 18608 | set via set_records_per_key(), works fine. */ | ||
| 18609 | |||
| 18610 | ulong rec_per_key_int = static_cast<ulong>( | ||
| 18611 |
1/2✓ Branch 0 taken 24114808 times.
✗ Branch 1 not taken.
|
24114802 | innodb_rec_per_key(index, (ulint)j, stats.records)); |
| 18612 | |||
| 18613 | /* Since MySQL seems to favor table scans | ||
| 18614 | too much over index searches, we pretend | ||
| 18615 | index selectivity is 2 times better than | ||
| 18616 | our estimate: */ | ||
| 18617 | |||
| 18618 | 24114808 | rec_per_key_int = rec_per_key_int / 2; | |
| 18619 | |||
| 18620 |
2/2✓ Branch 0 taken 17450042 times.
✓ Branch 1 taken 6664766 times.
|
24114808 | if (rec_per_key_int == 0) { |
| 18621 | 17450042 | rec_per_key_int = 1; | |
| 18622 | } | ||
| 18623 | |||
| 18624 | 24114808 | key->rec_per_key[j] = rec_per_key_int; | |
| 18625 | } | ||
| 18626 | } | ||
| 18627 | } | ||
| 18628 | |||
| 18629 |
2/2✓ Branch 0 taken 125423 times.
✓ Branch 1 taken 9164207 times.
|
9289630 | if (!(flag & HA_STATUS_NO_LOCK)) { |
| 18630 |
1/2✓ Branch 0 taken 125336 times.
✗ Branch 1 not taken.
|
125423 | dict_table_stats_unlock(ib_table, RW_S_LATCH); |
| 18631 | } | ||
| 18632 | |||
| 18633 |
2/2✓ Branch 0 taken 1736 times.
✓ Branch 1 taken 9287807 times.
|
9289543 | if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { |
| 18634 | 1736 | goto func_exit; | |
| 18635 | |||
| 18636 |
2/2✓ Branch 0 taken 488672 times.
✓ Branch 1 taken 8799135 times.
|
9287807 | } else if (flag & HA_STATUS_ERRKEY) { |
| 18637 | const dict_index_t *err_index; | ||
| 18638 | |||
| 18639 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 488672 times.
|
488672 | ut_a(m_prebuilt->trx); |
| 18640 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 488672 times.
|
488672 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 18641 | |||
| 18642 | 488672 | err_index = trx_get_error_index(m_prebuilt->trx); | |
| 18643 | |||
| 18644 |
2/2✓ Branch 0 taken 488670 times.
✓ Branch 1 taken 2 times.
|
488672 | if (err_index) { |
| 18645 |
1/2✓ Branch 0 taken 488670 times.
✗ Branch 1 not taken.
|
488670 | errkey = innobase_get_mysql_key_number_for_index(m_share, table, ib_table, |
| 18646 | err_index); | ||
| 18647 | } else { | ||
| 18648 | 2 | errkey = | |
| 18649 | (unsigned int)((m_prebuilt->trx->error_key_num == ULINT_UNDEFINED) | ||
| 18650 | ? ~0 | ||
| 18651 | 2 | : m_prebuilt->trx->error_key_num); | |
| 18652 | } | ||
| 18653 | } | ||
| 18654 | |||
| 18655 |
4/4✓ Branch 0 taken 9174962 times.
✓ Branch 1 taken 112845 times.
✓ Branch 2 taken 99755 times.
✓ Branch 3 taken 13090 times.
|
9287807 | if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) { |
| 18656 |
1/2✓ Branch 0 taken 13090 times.
✗ Branch 1 not taken.
|
13090 | ulonglong auto_inc_val = innobase_peek_autoinc(ib_table, true); |
| 18657 | /* Initialize autoinc value if not set. */ | ||
| 18658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13090 times.
|
13090 | if (auto_inc_val == 0) { |
| 18659 | ✗ | dict_table_autoinc_lock(m_prebuilt->table); | |
| 18660 | ✗ | innobase_initialize_autoinc(); | |
| 18661 | ✗ | dict_table_autoinc_unlock(m_prebuilt->table); | |
| 18662 | |||
| 18663 | ✗ | auto_inc_val = innobase_peek_autoinc(ib_table, true); | |
| 18664 | } | ||
| 18665 | 13090 | stats.auto_increment_value = auto_inc_val; | |
| 18666 | } | ||
| 18667 | |||
| 18668 | 9274717 | func_exit: | |
| 18669 | 9289543 | m_prebuilt->trx->op_info = (char *)""; | |
| 18670 | |||
| 18671 | 9289543 | return 0; | |
| 18672 | 9289543 | } | |
| 18673 | |||
| 18674 | /** Returns statistics information of the table to the MySQL interpreter, | ||
| 18675 | in various fields of the handle object. | ||
| 18676 | @return HA_ERR_* error code or 0 */ | ||
| 18677 | |||
| 18678 | 9375435 | int ha_innobase::info(uint flag) /*!< in: what information is requested */ | |
| 18679 | { | ||
| 18680 | 9375435 | return (info_low(flag, false /* not ANALYZE */)); | |
| 18681 | } | ||
| 18682 | |||
| 18683 | /** Get the autoincrement for the given table id which is | ||
| 18684 | not in the cache. | ||
| 18685 | @param[in] se_private_id InnoDB table id | ||
| 18686 | @param[in] tbl_se_private_data table SE private data | ||
| 18687 | @return autoincrement value for the given table_id. */ | ||
| 18688 | 27 | static uint64_t innodb_get_auto_increment_for_uncached( | |
| 18689 | dd::Object_id se_private_id, const dd::Properties &tbl_se_private_data) { | ||
| 18690 | 27 | uint64_t autoinc = 0; | |
| 18691 | 27 | uint64_t meta_autoinc = 0; | |
| 18692 | |||
| 18693 | bool exists = | ||
| 18694 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
27 | tbl_se_private_data.exists(dd_table_key_strings[DD_TABLE_AUTOINC]); |
| 18695 | |||
| 18696 | /** Get the auto_increment from the table SE private data. */ | ||
| 18697 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (exists) { |
| 18698 | ✗ | tbl_se_private_data.get(dd_table_key_strings[DD_TABLE_AUTOINC], &autoinc); | |
| 18699 | } | ||
| 18700 | |||
| 18701 | /** Get the auto_increment value from innodb_dynamic_metadata | ||
| 18702 | table. */ | ||
| 18703 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | mutex_enter(&dict_persist->mutex); |
| 18704 | |||
| 18705 | 27 | DDTableBuffer *table_buffer = dict_persist->table_buffer; | |
| 18706 | |||
| 18707 | uint64_t version; | ||
| 18708 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | std::string *readmeta = table_buffer->get(se_private_id, &version); |
| 18709 | |||
| 18710 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (readmeta->length() != 0) { |
| 18711 | ✗ | PersistentTableMetadata metadata(se_private_id, version); | |
| 18712 | |||
| 18713 | ✗ | dict_table_read_dynamic_metadata( | |
| 18714 | ✗ | reinterpret_cast<const byte *>(readmeta->data()), readmeta->length(), | |
| 18715 | &metadata); | ||
| 18716 | |||
| 18717 | ✗ | meta_autoinc = metadata.get_autoinc(); | |
| 18718 | } | ||
| 18719 | |||
| 18720 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | mutex_exit(&dict_persist->mutex); |
| 18721 | |||
| 18722 | 27 | ut::delete_(readmeta); | |
| 18723 | |||
| 18724 | 27 | return (std::max(meta_autoinc, autoinc)); | |
| 18725 | } | ||
| 18726 | |||
| 18727 | /** Retrieves table statistics only for uncache table only. | ||
| 18728 | @param[in] db_name database name | ||
| 18729 | @param[in] tbl_name table name | ||
| 18730 | @param[in] norm_name tablespace name | ||
| 18731 | @param[in] se_private_id InnoDB table id | ||
| 18732 | @param[in] ts_se_private_data tablespace se private data | ||
| 18733 | @param[in] tbl_se_private_data table se private data | ||
| 18734 | @param[in] stat_flags flags used to retrieve specific stats | ||
| 18735 | @param[in,out] stats structure to save the retrieved statistics | ||
| 18736 | @return true if the stats information filled successfully | ||
| 18737 | @return false if tablespace is missing or table doesn't have persistent | ||
| 18738 | stats. */ | ||
| 18739 | 35 | static bool innodb_get_table_statistics_for_uncached( | |
| 18740 | const char *db_name, const char *tbl_name, const char *norm_name, | ||
| 18741 | dd::Object_id se_private_id, const dd::Properties &ts_se_private_data, | ||
| 18742 | const dd::Properties &tbl_se_private_data, ulint stat_flags, | ||
| 18743 | ha_statistics *stats) { | ||
| 18744 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35 | TableStatsRecord stat_info; |
| 18745 | space_id_t space_id; | ||
| 18746 | |||
| 18747 |
3/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 27 times.
|
35 | if (!row_search_table_stats(db_name, tbl_name, stat_info)) { |
| 18748 | 8 | return (false); | |
| 18749 | } | ||
| 18750 | |||
| 18751 | /** Server passes dummy ts_se_private_data for file_per_table | ||
| 18752 | tablespace. In that case, InnoDB should find the space_id using | ||
| 18753 | the tablespace name. */ | ||
| 18754 |
2/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
|
27 | bool exists = ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID]); |
| 18755 | |||
| 18756 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (exists) { |
| 18757 | ✗ | ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id); | |
| 18758 | } else { | ||
| 18759 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | space_id = fil_space_get_id_by_name(norm_name); |
| 18760 | |||
| 18761 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (space_id == SPACE_UNKNOWN) { |
| 18762 | ✗ | return (false); | |
| 18763 | } | ||
| 18764 | } | ||
| 18765 | |||
| 18766 | fil_space_t *space; | ||
| 18767 | uint32_t fsp_flags; | ||
| 18768 | |||
| 18769 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | space = fil_space_acquire(space_id); |
| 18770 | |||
| 18771 | /** Tablespace is missing in this case. */ | ||
| 18772 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (space == nullptr) { |
| 18773 | ✗ | return (false); | |
| 18774 | } | ||
| 18775 | |||
| 18776 | 27 | fsp_flags = space->flags; | |
| 18777 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | page_size_t page_size(fsp_flags); |
| 18778 | |||
| 18779 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (stat_flags & HA_STATUS_VARIABLE_EXTRA) { |
| 18780 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | ulint avail_space = fsp_get_available_space_in_free_extents(space); |
| 18781 | 27 | stats->delete_length = avail_space * 1024; | |
| 18782 | } | ||
| 18783 | |||
| 18784 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | fil_space_release(space); |
| 18785 | |||
| 18786 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (stat_flags & HA_STATUS_AUTO) { |
| 18787 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | stats->auto_increment_value = innodb_get_auto_increment_for_uncached( |
| 18788 | se_private_id, tbl_se_private_data); | ||
| 18789 | } | ||
| 18790 | |||
| 18791 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (stat_flags & HA_STATUS_TIME) { |
| 18792 | 27 | stats->update_time = (time_t)NULL; | |
| 18793 | } | ||
| 18794 | |||
| 18795 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (stat_flags & HA_STATUS_VARIABLE) { |
| 18796 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | stats->records = static_cast<ha_rows>(stat_info.get_n_rows()); |
| 18797 | 27 | stats->data_file_length = | |
| 18798 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | static_cast<ulonglong>(stat_info.get_clustered_index_size()) * |
| 18799 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | page_size.physical(); |
| 18800 | 27 | stats->index_file_length = | |
| 18801 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | static_cast<ulonglong>(stat_info.get_sum_of_other_index_size()) * |
| 18802 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | page_size.physical(); |
| 18803 | |||
| 18804 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 11 times.
|
27 | if (stats->records == 0) { |
| 18805 | 16 | stats->mean_rec_length = 0; | |
| 18806 | } else { | ||
| 18807 | 11 | stats->mean_rec_length = | |
| 18808 | 11 | static_cast<ulong>(stats->data_file_length / stats->records); | |
| 18809 | } | ||
| 18810 | } | ||
| 18811 | |||
| 18812 | 27 | return (true); | |
| 18813 | 35 | } | |
| 18814 | |||
| 18815 | 3528 | static bool innobase_get_table_statistics( | |
| 18816 | const char *db_name, const char *table_name, dd::Object_id se_private_id, | ||
| 18817 | const dd::Properties &ts_se_private_data, | ||
| 18818 | const dd::Properties &tbl_se_private_data, uint stat_flags, | ||
| 18819 | ha_statistics *stats) { | ||
| 18820 | char norm_name[FN_REFLEN]; | ||
| 18821 | dict_table_t *ib_table; | ||
| 18822 | |||
| 18823 | char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1]; | ||
| 18824 | bool truncated; | ||
| 18825 |
1/2✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
|
3528 | build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0, |
| 18826 | &truncated); | ||
| 18827 | |||
| 18828 |
4/8✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3528 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3528 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3528 times.
|
3528 | if (truncated || !normalize_table_name(norm_name, buf)) { |
| 18829 | ✗ | ut_d(ut_error); | |
| 18830 | ut_o(return true); // (HA_ERR_TOO_LONG_PATH); | ||
| 18831 | } | ||
| 18832 | |||
| 18833 | 3528 | MDL_ticket *mdl = nullptr; | |
| 18834 |
1/2✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
|
3528 | THD *thd = current_thd; |
| 18835 | |||
| 18836 |
1/2✓ Branch 0 taken 3528 times.
✗ Branch 1 not taken.
|
3528 | ib_table = dd_table_open_on_name_in_mem(norm_name, false); |
| 18837 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 3493 times.
|
3528 | if (ib_table == nullptr) { |
| 18838 |
3/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 8 times.
|
35 | if (innodb_get_table_statistics_for_uncached( |
| 18839 | db_name, table_name, norm_name, se_private_id, ts_se_private_data, | ||
| 18840 | tbl_se_private_data, stat_flags, stats)) { | ||
| 18841 | 27 | return (false); | |
| 18842 | } | ||
| 18843 | |||
| 18844 | /** If the table doesn't have persistent stats then | ||
| 18845 | load the table from disk. */ | ||
| 18846 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false, |
| 18847 | DICT_ERR_IGNORE_NONE); | ||
| 18848 | |||
| 18849 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (ib_table == nullptr) { |
| 18850 | ✗ | return (true); | |
| 18851 | } | ||
| 18852 | } | ||
| 18853 | |||
| 18854 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | if (stat_flags & HA_STATUS_AUTO) { |
| 18855 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | stats->auto_increment_value = innobase_peek_autoinc(ib_table, false); |
| 18856 | } | ||
| 18857 | |||
| 18858 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | if (stat_flags & HA_STATUS_TIME) { |
| 18859 | 3501 | stats->update_time = static_cast<ulong>( | |
| 18860 | 3501 | std::chrono::system_clock::to_time_t(ib_table->update_time.load())); | |
| 18861 | } | ||
| 18862 | |||
| 18863 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | if (stat_flags & HA_STATUS_VARIABLE_EXTRA) { |
| 18864 |
2/4✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3501 times.
✗ Branch 3 not taken.
|
3501 | calculate_delete_length_stat(ib_table, stats, current_thd); |
| 18865 | } | ||
| 18866 | |||
| 18867 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | if (stat_flags & HA_STATUS_VARIABLE) { |
| 18868 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | dict_stats_init(ib_table); |
| 18869 | |||
| 18870 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3501 times.
|
3501 | ut_a(ib_table->stat_initialized); |
| 18871 | |||
| 18872 | /* Note it may look like ib_table->* arguments are | ||
| 18873 | redundant. If you see the usage of this call in info_low(), | ||
| 18874 | the stats can be retrieved while holding a latch if | ||
| 18875 | !HA_STATUS_NO_LOCK is passed. */ | ||
| 18876 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | calculate_index_size_stats(ib_table, ib_table->stat_n_rows, |
| 18877 | ib_table->stat_clustered_index_size, | ||
| 18878 | ib_table->stat_sum_of_other_index_sizes, stats); | ||
| 18879 | } | ||
| 18880 | |||
| 18881 |
1/2✓ Branch 0 taken 3501 times.
✗ Branch 1 not taken.
|
3501 | dd_table_close(ib_table, thd, &mdl, false); |
| 18882 | |||
| 18883 | 3501 | return (false); | |
| 18884 | } | ||
| 18885 | |||
| 18886 | 727 | static bool innobase_get_index_column_cardinality( | |
| 18887 | const char *db_name, const char *table_name, const char *index_name, uint, | ||
| 18888 | uint column_ordinal_position, dd::Object_id, ulonglong *cardinality) { | ||
| 18889 | char norm_name[FN_REFLEN]; | ||
| 18890 | dict_table_t *ib_table; | ||
| 18891 | 727 | bool failure = true; | |
| 18892 | |||
| 18893 | char buf[2 * NAME_CHAR_LEN * 5 + 2 + 1]; | ||
| 18894 | bool truncated; | ||
| 18895 |
1/2✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
|
727 | build_table_filename(buf, sizeof(buf), db_name, table_name, nullptr, 0, |
| 18896 | &truncated); | ||
| 18897 | |||
| 18898 |
4/8✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 727 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 727 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 727 times.
|
727 | if (truncated || !normalize_table_name(norm_name, buf)) { |
| 18899 | /* purecov: begin inspected */ | ||
| 18900 | ✗ | ut_d(ut_error); | |
| 18901 | ut_o(return (true)); | ||
| 18902 | /* purecov: end */ | ||
| 18903 | } | ||
| 18904 | |||
| 18905 | 727 | MDL_ticket *mdl = nullptr; | |
| 18906 |
1/2✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
|
727 | THD *thd = current_thd; |
| 18907 | |||
| 18908 |
1/2✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
|
727 | ib_table = dd_table_open_on_name_in_mem(norm_name, false); |
| 18909 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 722 times.
|
727 | if (ib_table == nullptr) { |
| 18910 |
2/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (row_search_index_stats(db_name, table_name, index_name, |
| 18911 | column_ordinal_position, cardinality)) { | ||
| 18912 | 5 | return (false); | |
| 18913 | } | ||
| 18914 | |||
| 18915 | /** If the table doesn't have persistent stats then | ||
| 18916 | load the table from disk. */ | ||
| 18917 | ✗ | ib_table = dd_table_open_on_name(thd, &mdl, norm_name, false, | |
| 18918 | DICT_ERR_IGNORE_NONE); | ||
| 18919 | |||
| 18920 | ✗ | if (ib_table == nullptr) { | |
| 18921 | ✗ | return (true); | |
| 18922 | } | ||
| 18923 | } | ||
| 18924 | |||
| 18925 |
2/4✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 722 times.
|
722 | if (ib_table->is_fts_aux()) { |
| 18926 | /* Server should not ask for Stats for Internal Tables */ | ||
| 18927 | ✗ | dd_table_close(ib_table, thd, &mdl, false); | |
| 18928 | ✗ | ut_d(ut_error); | |
| 18929 | ut_o(return (true)); | ||
| 18930 | } | ||
| 18931 | |||
| 18932 |
5/10✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 256 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 978 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 978 times.
✗ Branch 9 not taken.
|
978 | for (const dict_index_t *index : ib_table->indexes) { |
| 18933 |
6/8✓ Branch 0 taken 978 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 978 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 722 times.
✓ Branch 5 taken 256 times.
✓ Branch 6 taken 722 times.
✓ Branch 7 taken 256 times.
|
978 | if (index->is_committed() && ut_strcmp(index_name, index->name) == 0) { |
| 18934 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 662 times.
|
722 | if (ib_table->stat_initialized == 0) { |
| 18935 |
1/2✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
|
60 | dict_stats_init(ib_table); |
| 18936 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
|
60 | ut_a(ib_table->stat_initialized != 0); |
| 18937 | } | ||
| 18938 | |||
| 18939 |
2/4✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 722 times.
✗ Branch 3 not taken.
|
722 | DEBUG_SYNC(thd, "innodb.after_init_check"); |
| 18940 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 707 times.
|
722 | if (index->type & (DICT_FTS | DICT_SPATIAL)) { |
| 18941 | /* For these indexes innodb_rec_per_key is | ||
| 18942 | fixed as 1.0 */ | ||
| 18943 | 15 | *cardinality = ib_table->stat_n_rows; | |
| 18944 | } else { | ||
| 18945 | 707 | uint64_t n_rows = ib_table->stat_n_rows; | |
| 18946 | double records = | ||
| 18947 | 1414 | (n_rows / | |
| 18948 |
1/2✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
|
707 | innodb_rec_per_key(index, (ulint)column_ordinal_position, n_rows)); |
| 18949 | 707 | *cardinality = static_cast<ulonglong>(round(records)); | |
| 18950 | } | ||
| 18951 | |||
| 18952 | 722 | failure = false; | |
| 18953 | 722 | break; | |
| 18954 | } | ||
| 18955 | } | ||
| 18956 | |||
| 18957 |
1/2✓ Branch 0 taken 722 times.
✗ Branch 1 not taken.
|
722 | dd_table_close(ib_table, thd, &mdl, false); |
| 18958 | 722 | return (failure); | |
| 18959 | } | ||
| 18960 | |||
| 18961 | 858 | static bool innobase_is_tablespace_keyring_pre_v3_encrypted( | |
| 18962 | const dd::Tablespace &tablespace, int &error) { | ||
| 18963 | 858 | error = 0; | |
| 18964 | 858 | space_id_t id = 0; | |
| 18965 | |||
| 18966 |
3/6✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 858 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 858 times.
|
858 | ut_ad(innobase_strcasecmp(tablespace.engine().c_str(), "InnoDB") == 0); |
| 18967 | |||
| 18968 |
4/8✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 858 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 858 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 858 times.
|
858 | if (tablespace.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id)) |
| 18969 | ✗ | return true; | |
| 18970 | |||
| 18971 | /* Make sure tablespace is loaded. */ | ||
| 18972 |
1/2✓ Branch 0 taken 858 times.
✗ Branch 1 not taken.
|
858 | fil_space_t *space = fil_space_get(id); |
| 18973 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 849 times.
|
858 | if (space == nullptr) { |
| 18974 | 9 | error = HA_ERR_TABLESPACE_MISSING; | |
| 18975 | 9 | return false; | |
| 18976 | } | ||
| 18977 | |||
| 18978 | // If page0 was read and it has crypt - we can check if it is encrypted here | ||
| 18979 | // if crypt_data is null it means that page0 may not have yet been read - we | ||
| 18980 | // will read it in fil_space_open_if_needed and recheck if crypt_data is null | ||
| 18981 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 849 times.
|
849 | if (space->crypt_data != nullptr) |
| 18982 | ✗ | return is_space_keyring_pre_v3_encrypted(space); | |
| 18983 | |||
| 18984 |
1/2✓ Branch 0 taken 849 times.
✗ Branch 1 not taken.
|
849 | fil_space_open_if_needed(space); |
| 18985 | |||
| 18986 | // We do not need to care about mutexes as this function is only called during | ||
| 18987 | // the upgrade | ||
| 18988 |
1/2✓ Branch 0 taken 849 times.
✗ Branch 1 not taken.
|
849 | return is_space_keyring_pre_v3_encrypted(space); |
| 18989 | } | ||
| 18990 | |||
| 18991 | 476515 | static bool innobase_get_tablespace_type(const dd::Tablespace &space, | |
| 18992 | Tablespace_type *space_type) { | ||
| 18993 | 476515 | space_id_t id = 0; | |
| 18994 | 476515 | uint32_t flags = 0; | |
| 18995 | |||
| 18996 |
3/6✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476515 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 476515 times.
|
476515 | ut_ad(innobase_strcasecmp(space.engine().c_str(), "InnoDB") == 0); |
| 18997 | |||
| 18998 |
5/12✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476515 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 476515 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 476515 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 476515 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
1429545 | if (space.se_private_data().get(dd_space_key_strings[DD_SPACE_ID], &id) || |
| 18999 |
6/14✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476515 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 476515 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 476515 times.
✓ Branch 8 taken 476515 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 476515 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
953030 | space.se_private_data().get(dd_space_key_strings[DD_SPACE_FLAGS], |
| 19000 | &flags)) { | ||
| 19001 | ✗ | return true; | |
| 19002 | } | ||
| 19003 | |||
| 19004 |
5/6✓ Branch 0 taken 476515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56176 times.
✓ Branch 3 taken 420339 times.
✓ Branch 4 taken 56176 times.
✓ Branch 5 taken 420339 times.
|
532691 | if (space.id() == MYSQL_TABLESPACE_DD_ID && |
| 19005 |
1/2✓ Branch 0 taken 56176 times.
✗ Branch 1 not taken.
|
56176 | id == dict_sys_t::s_dict_space_id) { |
| 19006 | 56176 | *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY; | |
| 19007 |
2/2✓ Branch 0 taken 737 times.
✓ Branch 1 taken 419602 times.
|
420339 | } else if (id == TRX_SYS_SPACE) { |
| 19008 | 737 | *space_type = Tablespace_type::SPACE_TYPE_SYSTEM; | |
| 19009 |
3/4✓ Branch 0 taken 419602 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 419567 times.
|
419602 | } else if (fsp_is_undo_tablespace(id)) { |
| 19010 | 35 | *space_type = Tablespace_type::SPACE_TYPE_UNDO; | |
| 19011 |
3/4✓ Branch 0 taken 419567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 419550 times.
|
419567 | } else if (fsp_is_system_temporary(id)) { |
| 19012 | 17 | *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY; | |
| 19013 |
6/8✓ Branch 0 taken 409064 times.
✓ Branch 1 taken 10486 times.
✓ Branch 2 taken 409064 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 409064 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 409064 times.
✓ Branch 7 taken 10486 times.
|
419550 | } else if (fsp_is_shared_tablespace(flags) && fsp_is_ibd_tablespace(id)) { |
| 19014 | 409064 | *space_type = Tablespace_type::SPACE_TYPE_SHARED; | |
| 19015 |
2/4✓ Branch 0 taken 10486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10486 times.
✗ Branch 3 not taken.
|
10486 | } else if (fsp_is_file_per_table(id, flags)) { |
| 19016 | 10486 | *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT; | |
| 19017 | } else { | ||
| 19018 | ✗ | ut_d(ut_error); | |
| 19019 | ut_o(return true); | ||
| 19020 | } | ||
| 19021 | |||
| 19022 | 476515 | return false; | |
| 19023 | } | ||
| 19024 | |||
| 19025 | /** Get the tablespace type given the name. | ||
| 19026 | |||
| 19027 | @param[in] tablespace_name tablespace name | ||
| 19028 | @param[out] space_type type of space | ||
| 19029 | |||
| 19030 | @return Operation status. | ||
| 19031 | @retval false on success and true for failure. | ||
| 19032 | */ | ||
| 19033 | 1175855 | static bool innobase_get_tablespace_type_by_name(const char *tablespace_name, | |
| 19034 | Tablespace_type *space_type) { | ||
| 19035 |
6/6✓ Branch 0 taken 267370 times.
✓ Branch 1 taken 908485 times.
✓ Branch 2 taken 864 times.
✓ Branch 3 taken 266506 times.
✓ Branch 4 taken 908488 times.
✓ Branch 5 taken 861 times.
|
1175855 | if ((tablespace_name == nullptr && srv_file_per_table) || |
| 19036 | 908488 | (tablespace_name && | |
| 19037 |
2/2✓ Branch 0 taken 1234 times.
✓ Branch 1 taken 907254 times.
|
908488 | 0 == strcmp(tablespace_name, dict_sys_t::s_file_per_table_name))) { |
| 19038 | 267740 | *space_type = Tablespace_type::SPACE_TYPE_IMPLICIT; | |
| 19039 |
4/6✓ Branch 0 taken 864 times.
✓ Branch 1 taken 907251 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 864 times.
✓ Branch 4 taken 907264 times.
✗ Branch 5 not taken.
|
908115 | } else if ((tablespace_name == nullptr && !srv_file_per_table) || |
| 19040 | 907264 | (tablespace_name && | |
| 19041 |
2/2✓ Branch 0 taken 1117 times.
✓ Branch 1 taken 906147 times.
|
907264 | 0 == strcmp(tablespace_name, dict_sys_t::s_sys_space_name))) { |
| 19042 | 1981 | *space_type = Tablespace_type::SPACE_TYPE_SYSTEM; | |
| 19043 |
2/2✓ Branch 0 taken 902547 times.
✓ Branch 1 taken 3587 times.
|
906134 | } else if (0 == strcmp(tablespace_name, dict_sys_t::s_dd_space_name)) { |
| 19044 | 902547 | *space_type = Tablespace_type::SPACE_TYPE_DICTIONARY; | |
| 19045 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3579 times.
|
3587 | } else if (0 == strcmp(tablespace_name, dict_sys_t::s_temp_space_name)) { |
| 19046 | 8 | *space_type = Tablespace_type::SPACE_TYPE_TEMPORARY; | |
| 19047 |
1/2✓ Branch 0 taken 3592 times.
✗ Branch 1 not taken.
|
3579 | } else if (0 == strcmp(tablespace_name, |
| 19048 | 3592 | dict_sys_t::s_default_undo_space_name_1) || | |
| 19049 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3592 times.
|
3592 | 0 == strcmp(tablespace_name, |
| 19050 | dict_sys_t::s_default_undo_space_name_2)) { | ||
| 19051 | /* | ||
| 19052 | TODO: This function doesn't consider user created UNDO | ||
| 19053 | tablespaces because, as of now this function is not being | ||
| 19054 | called for UNDO tablesapces. But should consider this in | ||
| 19055 | future for completeness. | ||
| 19056 | */ | ||
| 19057 | ✗ | *space_type = Tablespace_type::SPACE_TYPE_UNDO; | |
| 19058 | } else { | ||
| 19059 | 3592 | *space_type = Tablespace_type::SPACE_TYPE_SHARED; | |
| 19060 | } | ||
| 19061 | |||
| 19062 | 1175855 | return false; | |
| 19063 | } | ||
| 19064 | |||
| 19065 | 281326 | static bool innobase_get_tablespace_statistics( | |
| 19066 | const char *tablespace_name, const char *file_name, | ||
| 19067 | const dd::Properties &ts_se_private_data, ha_tablespace_statistics *stats) { | ||
| 19068 | /* Tablespace does not have space id stored. */ | ||
| 19069 |
3/6✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 281326 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 281326 times.
|
281326 | if (!ts_se_private_data.exists(dd_space_key_strings[DD_SPACE_ID])) { |
| 19070 | ✗ | my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name); | |
| 19071 | ✗ | return (DD_FAILURE); | |
| 19072 | } | ||
| 19073 | |||
| 19074 | space_id_t space_id; | ||
| 19075 | |||
| 19076 |
2/4✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 281326 times.
✗ Branch 3 not taken.
|
281326 | ts_se_private_data.get(dd_space_key_strings[DD_SPACE_ID], &space_id); |
| 19077 | |||
| 19078 |
3/4✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56482 times.
✓ Branch 3 taken 224844 times.
|
281326 | if (fsp_is_undo_tablespace(space_id)) { |
| 19079 | /* Get the ddl_mutex so that if an undo truncation is happening by | ||
| 19080 | the purge thread, it will complete before we continue. */ | ||
| 19081 |
1/2✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
|
56482 | mutex_enter(&undo::ddl_mutex); |
| 19082 | |||
| 19083 | /* When selecting information_schema.files, no MVCC is used. So it is | ||
| 19084 | possible to read an uncommitted DD record that indicates the undo | ||
| 19085 | space is empty and shows the new space_id after a truncation. | ||
| 19086 | Adjust for that possibility by always using the current space_id. */ | ||
| 19087 |
1/2✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
|
56482 | undo::spaces->s_lock(); |
| 19088 | 56482 | space_id_t undo_num = undo::id2num(space_id); | |
| 19089 |
1/2✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
|
56482 | undo::Tablespace *undo_space = undo::spaces->find(undo_num); |
| 19090 |
2/2✓ Branch 0 taken 56475 times.
✓ Branch 1 taken 7 times.
|
56482 | if (undo_space != nullptr) { |
| 19091 | 56475 | space_id = undo_space->id(); | |
| 19092 | } | ||
| 19093 |
1/2✓ Branch 0 taken 56482 times.
✗ Branch 1 not taken.
|
56482 | undo::spaces->s_unlock(); |
| 19094 | } | ||
| 19095 | |||
| 19096 |
1/2✓ Branch 0 taken 281326 times.
✗ Branch 1 not taken.
|
281326 | auto space = fil_space_acquire(space_id); |
| 19097 | |||
| 19098 | /* Tablespace is missing in this case. */ | ||
| 19099 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 281287 times.
|
281326 | if (space == nullptr) { |
| 19100 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name); |
| 19101 |
3/4✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 32 times.
|
39 | if (fsp_is_undo_tablespace(space_id)) { |
| 19102 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | mutex_exit(&undo::ddl_mutex); |
| 19103 | } | ||
| 19104 | 39 | return (DD_FAILURE); | |
| 19105 | } | ||
| 19106 | |||
| 19107 | 281287 | stats->m_id = space->id; | |
| 19108 | |||
| 19109 | 281287 | const char *type = "TABLESPACE"; | |
| 19110 | |||
| 19111 | 281287 | fil_type_t purpose = space->purpose; | |
| 19112 | |||
| 19113 |
2/4✓ Branch 0 taken 253360 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27927 times.
✗ Branch 3 not taken.
|
281287 | switch (purpose) { |
| 19114 | 253360 | case FIL_TYPE_TABLESPACE: | |
| 19115 |
3/4✓ Branch 0 taken 253360 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56475 times.
✓ Branch 3 taken 196885 times.
|
253360 | if (fsp_is_undo_tablespace(space_id)) { |
| 19116 | 56475 | type = "UNDO LOG"; | |
| 19117 | 56475 | break; | |
| 19118 | } /* else fall through for TABLESPACE */ | ||
| 19119 | case FIL_TYPE_IMPORT: | ||
| 19120 | /* 'IMPORTING'is a status. The type is TABLESPACE. */ | ||
| 19121 | 196885 | break; | |
| 19122 | 27927 | case FIL_TYPE_TEMPORARY: | |
| 19123 | 27927 | type = "TEMPORARY"; | |
| 19124 | 27927 | break; | |
| 19125 | } | ||
| 19126 | |||
| 19127 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | stats->m_type = type; |
| 19128 | |||
| 19129 | 281287 | stats->m_free_extents = space->free_len; | |
| 19130 | |||
| 19131 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | page_size_t page_size{space->flags}; |
| 19132 | |||
| 19133 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | page_no_t extent_pages = fsp_get_extent_size_in_pages(page_size); |
| 19134 | |||
| 19135 | 281287 | stats->m_total_extents = space->size_in_header / extent_pages; | |
| 19136 | |||
| 19137 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | stats->m_extent_size = extent_pages * page_size.physical(); |
| 19138 | |||
| 19139 | 281287 | const fil_node_t *file = nullptr; | |
| 19140 | |||
| 19141 | /* Use only the basename when searching for system tablespaces since | ||
| 19142 | InnoDB places them in innodb_data_home_dir and the DD may only know | ||
| 19143 | the basename. Since they are open, they are in the right place. */ | ||
| 19144 | std::string search_name = | ||
| 19145 |
2/2✓ Branch 0 taken 27927 times.
✓ Branch 1 taken 225425 times.
|
253352 | (space->id == TRX_SYS_SPACE || space->id == dict_sys_t::s_temp_space_id) |
| 19146 | 281287 | ? Fil_path::get_basename(file_name) | |
| 19147 |
11/20✓ Branch 0 taken 253352 times.
✓ Branch 1 taken 27935 times.
✓ Branch 2 taken 55862 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 55862 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 225425 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 225425 times.
✓ Branch 9 taken 55862 times.
✓ Branch 10 taken 55862 times.
✓ Branch 11 taken 225425 times.
✓ Branch 12 taken 55862 times.
✓ Branch 13 taken 225425 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
1153075 | : file_name; |
| 19148 | |||
| 19149 | /* Normalize the file name to search for. */ | ||
| 19150 | 281287 | Fil_path::normalize(search_name); | |
| 19151 | |||
| 19152 | /* Find the fil_node_t that matches the filename. */ | ||
| 19153 |
1/2✓ Branch 0 taken 281303 times.
✗ Branch 1 not taken.
|
281303 | for (const auto &f : space->files) { |
| 19154 |
4/6✓ Branch 0 taken 281303 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 281303 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 281283 times.
✓ Branch 5 taken 20 times.
|
281303 | if (Fil_path::is_same_as(search_name, f.name)) { |
| 19155 | 281283 | file = &f; | |
| 19156 | 281283 | break; | |
| 19157 | } | ||
| 19158 | |||
| 19159 | /* Try to compare only the basename. */ | ||
| 19160 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
|
20 | if (space->id == TRX_SYS_SPACE || |
| 19161 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | space->id == dict_sys_t::s_temp_space_id) { |
| 19162 |
5/8✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 16 times.
|
20 | if (Fil_path::is_same_as(search_name, Fil_path::get_basename(f.name))) { |
| 19163 | 4 | file = &f; | |
| 19164 | 4 | break; | |
| 19165 | } | ||
| 19166 | } | ||
| 19167 | |||
| 19168 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (space->files.size() == 1) { |
| 19169 | ✗ | file = &f; | |
| 19170 | |||
| 19171 | ✗ | ib::info(ER_IB_MSG_570) | |
| 19172 | ✗ | << "Tablespace '" << tablespace_name << "'with DD filename '" | |
| 19173 | ✗ | << file_name << "' doesn't match the InnoDB filename '" << f.name | |
| 19174 | ✗ | << "'"; | |
| 19175 | } | ||
| 19176 | } | ||
| 19177 | |||
| 19178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 281287 times.
|
281287 | if (file == nullptr) { |
| 19179 | ✗ | ib::warn(ER_IB_MSG_571) << "Tablespace '" << tablespace_name << "'" | |
| 19180 | ✗ | << " filename is unknown. Use --innodb-directories" | |
| 19181 | ✗ | << " to tell InnoDB the location of the file."; | |
| 19182 | |||
| 19183 | ✗ | my_error(ER_TABLESPACE_MISSING, MYF(0), tablespace_name); | |
| 19184 | |||
| 19185 | ✗ | if (fsp_is_undo_tablespace(space_id)) { | |
| 19186 | ✗ | mutex_exit(&undo::ddl_mutex); | |
| 19187 | } | ||
| 19188 | |||
| 19189 | ✗ | return (DD_FAILURE); | |
| 19190 | } | ||
| 19191 | |||
| 19192 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | stats->m_initial_size = file->init_size * page_size.physical(); |
| 19193 | |||
| 19194 | /** Store maximum size */ | ||
| 19195 |
2/2✓ Branch 0 taken 281275 times.
✓ Branch 1 taken 12 times.
|
281287 | if (file->max_size >= PAGE_NO_MAX) { |
| 19196 | 281275 | stats->m_maximum_size = ~0ULL; | |
| 19197 | } else { | ||
| 19198 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | stats->m_maximum_size = file->max_size * page_size.physical(); |
| 19199 | } | ||
| 19200 | |||
| 19201 | /** Store autoextend size */ | ||
| 19202 | page_no_t extend_pages; | ||
| 19203 | |||
| 19204 |
2/2✓ Branch 0 taken 27935 times.
✓ Branch 1 taken 253352 times.
|
281287 | if (space->id == TRX_SYS_SPACE) { |
| 19205 |
1/2✓ Branch 0 taken 27935 times.
✗ Branch 1 not taken.
|
27935 | extend_pages = srv_sys_space.get_increment(); |
| 19206 | |||
| 19207 |
3/4✓ Branch 0 taken 253352 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27927 times.
✓ Branch 3 taken 225425 times.
|
253352 | } else if (fsp_is_system_temporary(space->id)) { |
| 19208 |
1/2✓ Branch 0 taken 27927 times.
✗ Branch 1 not taken.
|
27927 | extend_pages = srv_tmp_space.get_increment(); |
| 19209 | |||
| 19210 |
3/4✓ Branch 0 taken 225425 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56475 times.
✓ Branch 3 taken 168950 times.
|
225425 | } else if (fsp_is_undo_tablespace(space->id)) { |
| 19211 | 56475 | extend_pages = space->m_undo_extend; | |
| 19212 | |||
| 19213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168950 times.
|
168950 | } else if (space->autoextend_size_in_bytes > 0) { |
| 19214 | ✗ | extend_pages = space->autoextend_size_in_bytes / page_size.physical(); | |
| 19215 | } else { | ||
| 19216 |
1/2✓ Branch 0 taken 168950 times.
✗ Branch 1 not taken.
|
168950 | extend_pages = fsp_get_pages_to_extend_ibd(page_size, file->size); |
| 19217 | } | ||
| 19218 | |||
| 19219 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | stats->m_autoextend_size = extend_pages * page_size.physical(); |
| 19220 | |||
| 19221 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | auto avail_space = fsp_get_available_space_in_free_extents(space); |
| 19222 | |||
| 19223 | 281287 | stats->m_data_free = avail_space * 1024; | |
| 19224 | |||
| 19225 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 281287 times.
✓ Branch 2 taken 281287 times.
✗ Branch 3 not taken.
|
281287 | stats->m_status = (purpose == FIL_TYPE_IMPORT ? "IMPORTING" : "NORMAL"); |
| 19226 | |||
| 19227 |
1/2✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
|
281287 | fil_space_release(space); |
| 19228 | |||
| 19229 |
3/4✓ Branch 0 taken 281287 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56475 times.
✓ Branch 3 taken 224812 times.
|
281287 | if (fsp_is_undo_tablespace(space_id)) { |
| 19230 |
1/2✓ Branch 0 taken 56475 times.
✗ Branch 1 not taken.
|
56475 | mutex_exit(&undo::ddl_mutex); |
| 19231 | } | ||
| 19232 | |||
| 19233 | 281287 | return (DD_SUCCESS); | |
| 19234 | } | ||
| 19235 | |||
| 19236 | /** Enable indexes. | ||
| 19237 | @param[in] mode enable index mode. | ||
| 19238 | @return HA_ERR_* error code or 0 */ | ||
| 19239 | 504 | int ha_innobase::enable_indexes(uint mode) { | |
| 19240 | 504 | int error = HA_ERR_WRONG_COMMAND; | |
| 19241 | |||
| 19242 | /* Enable index only for intrinsic table. Behavior for all other | ||
| 19243 | table continue to remain same. */ | ||
| 19244 | |||
| 19245 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 504 times.
|
504 | if (m_prebuilt->table->is_intrinsic()) { |
| 19246 | ✗ | ut_ad(mode == HA_KEY_SWITCH_ALL); | |
| 19247 | ✗ | for (auto index : m_prebuilt->table->indexes) { | |
| 19248 | /* InnoDB being clustered index we can't disable/enable | ||
| 19249 | clustered index itself. */ | ||
| 19250 | ✗ | if (index->is_clustered()) { | |
| 19251 | ✗ | continue; | |
| 19252 | } | ||
| 19253 | |||
| 19254 | ✗ | index->allow_duplicates = false; | |
| 19255 | } | ||
| 19256 | ✗ | error = 0; | |
| 19257 | } | ||
| 19258 | |||
| 19259 | 504 | return (error); | |
| 19260 | } | ||
| 19261 | |||
| 19262 | /** Disable indexes. | ||
| 19263 | @param[in] mode disable index mode. | ||
| 19264 | @return HA_ERR_* error code or 0 */ | ||
| 19265 | 496 | int ha_innobase::disable_indexes(uint mode) { | |
| 19266 | 496 | int error = HA_ERR_WRONG_COMMAND; | |
| 19267 | |||
| 19268 | /* Disable index only for intrinsic table. Behavior for all other | ||
| 19269 | table continue to remain same. */ | ||
| 19270 | |||
| 19271 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 496 times.
|
496 | if (m_prebuilt->table->is_intrinsic()) { |
| 19272 | ✗ | ut_ad(mode == HA_KEY_SWITCH_ALL); | |
| 19273 | ✗ | for (auto index : m_prebuilt->table->indexes) { | |
| 19274 | /* InnoDB being clustered index we can't disable/enable | ||
| 19275 | clustered index itself. */ | ||
| 19276 | ✗ | if (index->is_clustered()) { | |
| 19277 | ✗ | continue; | |
| 19278 | } | ||
| 19279 | |||
| 19280 | ✗ | index->allow_duplicates = true; | |
| 19281 | } | ||
| 19282 | ✗ | error = 0; | |
| 19283 | } | ||
| 19284 | |||
| 19285 | 496 | return (error); | |
| 19286 | } | ||
| 19287 | |||
| 19288 | /** | ||
| 19289 | Updates index cardinalities of the table, based on random dives into | ||
| 19290 | each index tree. This does NOT calculate exact statistics on the table. | ||
| 19291 | @return HA_ADMIN_* error code or HA_ADMIN_OK */ | ||
| 19292 | |||
| 19293 | 5908 | int ha_innobase::analyze(THD *, /*!< in: connection thread handle */ | |
| 19294 | HA_CHECK_OPT *) /*!< in: currently ignored */ | ||
| 19295 | { | ||
| 19296 |
5/10✓ Branch 0 taken 5524 times.
✓ Branch 1 taken 384 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5524 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5908 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5908 times.
|
5908 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 19297 | m_share->ib_table->is_corrupt)) { | ||
| 19298 | ✗ | return (HA_ADMIN_CORRUPT); | |
| 19299 | } | ||
| 19300 | |||
| 19301 | /* Simply call info_low() with all the flags | ||
| 19302 | and request recalculation of the statistics */ | ||
| 19303 | 5908 | int ret = info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE, | |
| 19304 | true /* this is ANALYZE */); | ||
| 19305 | |||
| 19306 |
5/10✓ Branch 0 taken 5524 times.
✓ Branch 1 taken 384 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5524 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5908 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5908 times.
|
5908 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 19307 | m_share->ib_table->is_corrupt)) { | ||
| 19308 | ✗ | return (HA_ADMIN_CORRUPT); | |
| 19309 | } | ||
| 19310 | |||
| 19311 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5903 times.
|
5908 | if (ret != 0) { |
| 19312 | 5 | return (HA_ADMIN_FAILED); | |
| 19313 | } | ||
| 19314 | |||
| 19315 | 5903 | return (HA_ADMIN_OK); | |
| 19316 | } | ||
| 19317 | |||
| 19318 | /** This is mapped to "ALTER TABLE tablename ENGINE=InnoDB", which rebuilds | ||
| 19319 | the table in MySQL. */ | ||
| 19320 | |||
| 19321 | 2023 | int ha_innobase::optimize(THD *, /*!< in: connection thread handle */ | |
| 19322 | HA_CHECK_OPT *) /*!< in: currently ignored */ | ||
| 19323 | { | ||
| 19324 |
1/2✓ Branch 0 taken 2023 times.
✗ Branch 1 not taken.
|
2023 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 19325 | |||
| 19326 | /* FTS-FIXME: Since MySQL doesn't support engine-specific commands, | ||
| 19327 | we have to hijack some existing command in order to be able to test | ||
| 19328 | the new admin commands added in InnoDB's FTS support. For now, we | ||
| 19329 | use MySQL's OPTIMIZE command, normally mapped to ALTER TABLE in | ||
| 19330 | InnoDB (so it recreates the table anew), and map it to OPTIMIZE. | ||
| 19331 | |||
| 19332 | This works OK otherwise, but MySQL locks the entire table during | ||
| 19333 | calls to OPTIMIZE, which is undesirable. */ | ||
| 19334 | |||
| 19335 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2015 times.
|
2023 | if (innodb_optimize_fulltext_only) { |
| 19336 |
3/6✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
16 | if (m_prebuilt->table->fts && m_prebuilt->table->fts->cache && |
| 19337 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | !dict_table_is_discarded(m_prebuilt->table)) { |
| 19338 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | fts_sync_table(m_prebuilt->table, false, true, false); |
| 19339 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | fts_optimize_table(m_prebuilt->table); |
| 19340 | } | ||
| 19341 | 8 | return (HA_ADMIN_OK); | |
| 19342 | } else { | ||
| 19343 | 2015 | return (HA_ADMIN_TRY_ALTER); | |
| 19344 | } | ||
| 19345 | 2023 | } | |
| 19346 | |||
| 19347 | /** Tries to check that an InnoDB table is not corrupted. If corruption is | ||
| 19348 | noticed, prints to stderr information about it. In case of corruption | ||
| 19349 | may also assert a failure and crash the server. | ||
| 19350 | @return HA_ADMIN_CORRUPT or HA_ADMIN_OK */ | ||
| 19351 | |||
| 19352 | 3941 | int ha_innobase::check(THD *thd, /*!< in: user thread handle */ | |
| 19353 | HA_CHECK_OPT *check_opt) /*!< in: check options */ | ||
| 19354 | { | ||
| 19355 | dict_index_t *index; | ||
| 19356 | ulint n_rows; | ||
| 19357 | 3941 | ulint n_rows_in_table = ULINT_UNDEFINED; | |
| 19358 | 3941 | ulint n_dups = 0; | |
| 19359 | 3941 | bool is_ok = true; | |
| 19360 | ulint old_isolation_level; | ||
| 19361 | dberr_t ret; | ||
| 19362 | |||
| 19363 |
1/2✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
|
3941 | DBUG_TRACE; |
| 19364 |
2/4✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3941 times.
|
3941 | assert(thd == ha_thd()); |
| 19365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3941 times.
|
3941 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 19366 |
2/4✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3941 times.
|
3941 | ut_a(m_prebuilt->trx == thd_to_trx(thd)); |
| 19367 | |||
| 19368 |
1/2✓ Branch 0 taken 3941 times.
✗ Branch 1 not taken.
|
3941 | TrxInInnoDB trx_in_innodb(m_prebuilt->trx); |
| 19369 | |||
| 19370 |
2/2✓ Branch 0 taken 1261 times.
✓ Branch 1 taken 2680 times.
|
3941 | if (m_prebuilt->mysql_template == nullptr) { |
| 19371 | /* Build the template; we will use a dummy template | ||
| 19372 | in index scans done in checking */ | ||
| 19373 | |||
| 19374 |
1/2✓ Branch 0 taken 1261 times.
✗ Branch 1 not taken.
|
1261 | build_template(true); |
| 19375 | } | ||
| 19376 | |||
| 19377 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3937 times.
|
3941 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 19378 | 4 | ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_DISCARDED, | |
| 19379 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | table->s->table_name.str); |
| 19380 | |||
| 19381 | 4 | return HA_ADMIN_CORRUPT; | |
| 19382 | |||
| 19383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3937 times.
|
3937 | } else if (m_prebuilt->table->ibd_file_missing) { |
| 19384 | ✗ | ib_senderrf(thd, IB_LOG_LEVEL_ERROR, ER_TABLESPACE_MISSING, | |
| 19385 | ✗ | table->s->table_name.str); | |
| 19386 | |||
| 19387 | ✗ | return HA_ADMIN_CORRUPT; | |
| 19388 | } | ||
| 19389 | |||
| 19390 | 3937 | m_prebuilt->trx->op_info = "checking table"; | |
| 19391 | |||
| 19392 |
2/4✓ Branch 0 taken 3937 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3937 times.
|
3937 | if (m_prebuilt->table->is_corrupted()) { |
| 19393 | /* Now that the table is already marked as corrupted, | ||
| 19394 | there is no need to check any index of this table */ | ||
| 19395 | ✗ | m_prebuilt->trx->op_info = ""; | |
| 19396 | ✗ | if (thd_killed(m_user_thd)) { | |
| 19397 | ✗ | thd_set_kill_status(m_user_thd); | |
| 19398 | } | ||
| 19399 | |||
| 19400 | ✗ | return HA_ADMIN_CORRUPT; | |
| 19401 | } | ||
| 19402 | |||
| 19403 | 3937 | old_isolation_level = m_prebuilt->trx->isolation_level; | |
| 19404 | |||
| 19405 | /* We must run the index record counts at an isolation level | ||
| 19406 | >= READ COMMITTED, because a dirty read can see a wrong number | ||
| 19407 | of records in some index; to play safe, we use always | ||
| 19408 | REPEATABLE READ here */ | ||
| 19409 | 3937 | m_prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; | |
| 19410 | |||
| 19411 |
2/4✓ Branch 0 taken 3937 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3937 times.
|
3937 | ut_ad(!m_prebuilt->table->is_corrupted()); |
| 19412 | |||
| 19413 |
3/4✓ Branch 0 taken 3937 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6642 times.
✓ Branch 3 taken 3934 times.
|
10576 | for (index = m_prebuilt->table->first_index(); index != nullptr; |
| 19414 |
1/2✓ Branch 0 taken 6639 times.
✗ Branch 1 not taken.
|
6639 | index = index->next()) { |
| 19415 | /* If this is an index being created or dropped, skip */ | ||
| 19416 |
3/4✓ Branch 0 taken 6642 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6640 times.
|
6642 | if (!index->is_committed()) { |
| 19417 | 2 | continue; | |
| 19418 | } | ||
| 19419 | |||
| 19420 |
6/8✓ Branch 0 taken 6640 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6640 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6623 times.
✓ Branch 5 taken 17 times.
✓ Branch 6 taken 6623 times.
✓ Branch 7 taken 17 times.
|
6640 | if (!(check_opt->flags & T_QUICK) && !index->is_corrupted()) { |
| 19421 | /* Enlarge the fatal lock wait timeout during | ||
| 19422 | CHECK TABLE. */ | ||
| 19423 | srv_fatal_semaphore_wait_extend.fetch_add(1); | ||
| 19424 | |||
| 19425 |
1/2✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
|
6623 | bool valid = btr_validate_index(index, m_prebuilt->trx, false); |
| 19426 | |||
| 19427 | /* Restore the fatal lock wait timeout after | ||
| 19428 | CHECK TABLE. */ | ||
| 19429 | srv_fatal_semaphore_wait_extend.fetch_sub(1); | ||
| 19430 | |||
| 19431 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6623 times.
|
6623 | if (!valid) { |
| 19432 | ✗ | is_ok = false; | |
| 19433 | |||
| 19434 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, | |
| 19435 | "InnoDB: The B-tree of" | ||
| 19436 | " index %s is corrupted.", | ||
| 19437 | index->name()); | ||
| 19438 | ✗ | continue; | |
| 19439 | } | ||
| 19440 | } | ||
| 19441 | |||
| 19442 | /* Instead of invoking change_active_index(), set up | ||
| 19443 | a dummy template for non-locking reads, disabling | ||
| 19444 | access to the clustered index. */ | ||
| 19445 | 6640 | m_prebuilt->index = index; | |
| 19446 | |||
| 19447 |
1/2✓ Branch 0 taken 6640 times.
✗ Branch 1 not taken.
|
6640 | m_prebuilt->index_usable = m_prebuilt->index->is_usable(m_prebuilt->trx); |
| 19448 | |||
| 19449 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 6623 times.
|
6640 | if (!m_prebuilt->index_usable) { |
| 19450 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
|
17 | if (m_prebuilt->index->is_corrupted()) { |
| 19451 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
17 | push_warning_printf(m_user_thd, Sql_condition::SL_WARNING, |
| 19452 | HA_ERR_INDEX_CORRUPT, | ||
| 19453 | "InnoDB: Index %s is marked as" | ||
| 19454 | " corrupted", | ||
| 19455 | index->name()); | ||
| 19456 | 17 | is_ok = false; | |
| 19457 | } else { | ||
| 19458 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, | |
| 19459 | HA_ERR_TABLE_DEF_CHANGED, | ||
| 19460 | "InnoDB: Insufficient history for" | ||
| 19461 | " index %s", | ||
| 19462 | index->name()); | ||
| 19463 | } | ||
| 19464 | 17 | continue; | |
| 19465 | } | ||
| 19466 | |||
| 19467 | 6623 | m_prebuilt->sql_stat_start = true; | |
| 19468 | 6623 | m_prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE; | |
| 19469 | 6623 | m_prebuilt->n_template = 0; | |
| 19470 | 6623 | m_prebuilt->need_to_access_clustered = false; | |
| 19471 | |||
| 19472 |
1/2✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
|
6623 | m_prebuilt->clear_search_tuples(); |
| 19473 | |||
| 19474 | 6623 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 19475 | |||
| 19476 |
1/2✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
|
6623 | size_t max_threads = thd_parallel_read_threads(m_prebuilt->trx->mysql_thd); |
| 19477 | |||
| 19478 | /* Scan this index. */ | ||
| 19479 |
3/4✓ Branch 0 taken 6623 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 6575 times.
|
6623 | if (dict_index_is_spatial(index)) { |
| 19480 |
1/2✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
|
48 | ret = row_count_rtree_recs(m_prebuilt, &n_rows, &n_dups); |
| 19481 | } else { | ||
| 19482 |
1/2✓ Branch 0 taken 6574 times.
✗ Branch 1 not taken.
|
6575 | ret = row_scan_index_for_mysql(m_prebuilt, index, max_threads, true, |
| 19483 | &n_rows); | ||
| 19484 | } | ||
| 19485 | |||
| 19486 |
5/8✓ Branch 0 taken 6622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6620 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
6622 | DBUG_EXECUTE_IF( |
| 19487 | "dict_set_clust_index_corrupted", | ||
| 19488 | if (index->is_clustered()) { ret = DB_CORRUPTION; }); | ||
| 19489 | |||
| 19490 |
6/8✓ Branch 0 taken 6622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 6605 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 6 times.
|
6622 | DBUG_EXECUTE_IF( |
| 19491 | "dict_set_index_corrupted", | ||
| 19492 | if (!index->is_clustered()) { ret = DB_CORRUPTION; }); | ||
| 19493 | |||
| 19494 |
4/8✓ Branch 0 taken 6622 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6622 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6622 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6622 times.
|
6622 | if (ret == DB_INTERRUPTED || thd_killed(m_user_thd)) { |
| 19495 | /* Do not report error since this could happen | ||
| 19496 | during shutdown */ | ||
| 19497 | ✗ | break; | |
| 19498 | } | ||
| 19499 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6609 times.
|
6622 | if (ret != DB_SUCCESS) { |
| 19500 | /* Assume some kind of corruption. */ | ||
| 19501 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, |
| 19502 | "InnoDB: The B-tree of" | ||
| 19503 | " index %s is corrupted.", | ||
| 19504 | index->name()); | ||
| 19505 | 13 | is_ok = false; | |
| 19506 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
13 | dict_set_corrupted(index); |
| 19507 | } | ||
| 19508 | |||
| 19509 |
3/4✓ Branch 0 taken 6620 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3936 times.
✓ Branch 3 taken 2684 times.
|
6620 | if (index == m_prebuilt->table->first_index()) { |
| 19510 | 3936 | n_rows_in_table = n_rows; | |
| 19511 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 2600 times.
|
2641 | } else if (!(index->type & DICT_FTS) && (n_rows != n_rows_in_table) && |
| 19512 |
5/8✓ Branch 0 taken 2641 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 41 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 41 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2684 times.
|
5325 | (!index->is_multi_value()) && |
| 19513 | ✗ | (!dict_index_is_spatial(index) || (n_rows < n_rows_in_table) || | |
| 19514 | ✗ | (n_dups < n_rows - n_rows_in_table))) { | |
| 19515 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, | |
| 19516 | "InnoDB: Index '%-.200s' contains %lu" | ||
| 19517 | " entries, should be %lu.", | ||
| 19518 | index->name(), (ulong)n_rows, (ulong)n_rows_in_table); | ||
| 19519 | ✗ | is_ok = false; | |
| 19520 | ✗ | dict_set_corrupted(index); | |
| 19521 | } | ||
| 19522 | } | ||
| 19523 | |||
| 19524 | /* Restore the original isolation level */ | ||
| 19525 | 3934 | m_prebuilt->trx->isolation_level = | |
| 19526 | 3934 | static_cast<trx_t::isolation_level_t>(old_isolation_level); | |
| 19527 | |||
| 19528 | #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG | ||
| 19529 | /* We validate the whole adaptive hash index for all tables | ||
| 19530 | at every CHECK TABLE only when QUICK flag is not present. */ | ||
| 19531 | |||
| 19532 |
4/8✓ Branch 0 taken 3934 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3934 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3934 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3934 times.
|
3934 | if (!(check_opt->flags & T_QUICK) && !btr_search_validate()) { |
| 19533 | ✗ | push_warning(thd, Sql_condition::SL_WARNING, ER_NOT_KEYFILE, | |
| 19534 | "InnoDB: The adaptive hash index is corrupted."); | ||
| 19535 | ✗ | is_ok = false; | |
| 19536 | } | ||
| 19537 | #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ | ||
| 19538 | 3934 | m_prebuilt->trx->op_info = ""; | |
| 19539 |
2/4✓ Branch 0 taken 3934 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3934 times.
|
3934 | if (thd_killed(m_user_thd)) { |
| 19540 | ✗ | thd_set_kill_status(m_user_thd); | |
| 19541 | } | ||
| 19542 | |||
| 19543 |
5/10✓ Branch 0 taken 946 times.
✓ Branch 1 taken 2988 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 946 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3934 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3934 times.
|
3934 | if (UNIV_UNLIKELY(m_share && m_share->ib_table && |
| 19544 | m_share->ib_table->is_corrupt)) { | ||
| 19545 | ✗ | return HA_ADMIN_CORRUPT; | |
| 19546 | } | ||
| 19547 | |||
| 19548 |
2/2✓ Branch 0 taken 3918 times.
✓ Branch 1 taken 16 times.
|
3934 | return is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT; |
| 19549 | 3938 | } | |
| 19550 | |||
| 19551 | /** Tells something additional to the handler about how to do things. | ||
| 19552 | @return 0 or error number */ | ||
| 19553 | |||
| 19554 | 1004099314 | int ha_innobase::extra(enum ha_extra_function operation) | |
| 19555 | /*!< in: HA_EXTRA_FLUSH or some other flag */ | ||
| 19556 | { | ||
| 19557 |
1/2✓ Branch 0 taken 1004100936 times.
✗ Branch 1 not taken.
|
1004099314 | if (m_prebuilt->table) { |
| 19558 | #ifdef UNIV_DEBUG | ||
| 19559 |
2/2✓ Branch 0 taken 1004100323 times.
✓ Branch 1 taken 28 times.
|
1004100936 | if (m_prebuilt->table->n_ref_count > 0) |
| 19560 | #endif /* UNIV_DEBUG */ | ||
| 19561 | 1004100323 | update_thd(); | |
| 19562 | } | ||
| 19563 | |||
| 19564 | /* Warning: since it is not sure that MySQL calls external_lock | ||
| 19565 | before calling this function, the trx field in m_prebuilt can be | ||
| 19566 | obsolete! */ | ||
| 19567 | |||
| 19568 |
13/14✗ Branch 0 not taken.
✓ Branch 1 taken 108106047 times.
✓ Branch 2 taken 1225838 times.
✓ Branch 3 taken 1256145 times.
✓ Branch 4 taken 199018 times.
✓ Branch 5 taken 82637 times.
✓ Branch 6 taken 114538976 times.
✓ Branch 7 taken 2272419 times.
✓ Branch 8 taken 114539324 times.
✓ Branch 9 taken 2364461 times.
✓ Branch 10 taken 7725 times.
✓ Branch 11 taken 7723 times.
✓ Branch 12 taken 95101930 times.
✓ Branch 13 taken 564398572 times.
|
1004100815 | switch (operation) { |
| 19569 | ✗ | case HA_EXTRA_FLUSH: | |
| 19570 | ✗ | if (m_prebuilt->blob_heap) { | |
| 19571 | ✗ | row_mysql_prebuilt_free_blob_heap(m_prebuilt); | |
| 19572 | } | ||
| 19573 | |||
| 19574 | ✗ | if (m_prebuilt->compress_heap) { | |
| 19575 | ✗ | row_mysql_prebuilt_free_compress_heap(m_prebuilt); | |
| 19576 | } | ||
| 19577 | |||
| 19578 | ✗ | break; | |
| 19579 | 108106047 | case HA_EXTRA_RESET_STATE: | |
| 19580 | 108106047 | reset_template(); | |
| 19581 | 108105989 | m_prebuilt->replace = 0; | |
| 19582 | 108105989 | m_prebuilt->on_duplicate_key_update = 0; | |
| 19583 | 108105989 | break; | |
| 19584 | 1225838 | case HA_EXTRA_NO_KEYREAD: | |
| 19585 | 1225838 | m_prebuilt->read_just_key = 0; | |
| 19586 | 1225838 | break; | |
| 19587 | 1256145 | case HA_EXTRA_KEYREAD: | |
| 19588 | 1256145 | m_prebuilt->read_just_key = 1; | |
| 19589 | 1256145 | break; | |
| 19590 | 199018 | case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: | |
| 19591 | 199018 | m_prebuilt->keep_other_fields_on_keyread = 1; | |
| 19592 | 199018 | break; | |
| 19593 | |||
| 19594 | /* IMPORTANT: m_prebuilt->trx can be obsolete in | ||
| 19595 | this method, because it is not sure that MySQL | ||
| 19596 | calls external_lock before this method with the | ||
| 19597 | parameters below. We must not invoke update_thd() | ||
| 19598 | either, because the calling threads may change. | ||
| 19599 | CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */ | ||
| 19600 | 82637 | case HA_EXTRA_INSERT_WITH_UPDATE: | |
| 19601 | 82637 | m_prebuilt->on_duplicate_key_update = 1; | |
| 19602 | 82637 | break; | |
| 19603 | 114538976 | case HA_EXTRA_NO_IGNORE_DUP_KEY: | |
| 19604 | 114538976 | m_prebuilt->on_duplicate_key_update = 0; | |
| 19605 | 114538976 | break; | |
| 19606 | 2272419 | case HA_EXTRA_WRITE_CAN_REPLACE: | |
| 19607 | 2272419 | m_prebuilt->replace = 1; | |
| 19608 | 2272419 | break; | |
| 19609 | 114539324 | case HA_EXTRA_WRITE_CANNOT_REPLACE: | |
| 19610 | 114539324 | m_prebuilt->replace = 0; | |
| 19611 | 114539324 | break; | |
| 19612 | 2364461 | case HA_EXTRA_NO_READ_LOCKING: | |
| 19613 | 2364461 | m_prebuilt->no_read_locking = true; | |
| 19614 | 2364461 | break; | |
| 19615 | 7725 | case HA_EXTRA_BEGIN_ALTER_COPY: | |
| 19616 | 7725 | m_prebuilt->table->skip_alter_undo = 1; | |
| 19617 | 7725 | break; | |
| 19618 | 7723 | case HA_EXTRA_END_ALTER_COPY: | |
| 19619 | 7723 | m_prebuilt->table->skip_alter_undo = 0; | |
| 19620 | 7723 | break; | |
| 19621 | 95101930 | case HA_EXTRA_NO_AUTOINC_LOCKING: | |
| 19622 | 95101930 | m_prebuilt->no_autoinc_locking = true; | |
| 19623 | 95101930 | break; | |
| 19624 | 1004100757 | default: /* Do nothing */ | |
| 19625 | ; | ||
| 19626 | } | ||
| 19627 | |||
| 19628 | 1004100757 | return (0); | |
| 19629 | } | ||
| 19630 | |||
| 19631 | /** | ||
| 19632 | MySQL calls this method at the end of each statement. This method | ||
| 19633 | exists for readability only. ha_innobase::reset() doesn't give any | ||
| 19634 | clue about the method. */ | ||
| 19635 | |||
| 19636 | 114538733 | int ha_innobase::end_stmt() { | |
| 19637 |
2/2✓ Branch 0 taken 12352459 times.
✓ Branch 1 taken 102186274 times.
|
114538733 | if (m_prebuilt->blob_heap) { |
| 19638 | 12352459 | row_mysql_prebuilt_free_blob_heap(m_prebuilt); | |
| 19639 | } | ||
| 19640 | |||
| 19641 |
2/2✓ Branch 0 taken 3187 times.
✓ Branch 1 taken 114535565 times.
|
114538752 | if (m_prebuilt->compress_heap) { |
| 19642 | 3187 | row_mysql_prebuilt_free_compress_heap(m_prebuilt); | |
| 19643 | } | ||
| 19644 | |||
| 19645 | 114538752 | m_prebuilt->end_stmt(); | |
| 19646 | |||
| 19647 | 114538617 | reset_template(); | |
| 19648 | |||
| 19649 | 114539170 | m_ds_mrr.reset(); | |
| 19650 | |||
| 19651 | /* TODO: This should really be reset in reset_template() but for now | ||
| 19652 | it's safer to do it explicitly here. */ | ||
| 19653 | |||
| 19654 | /* This is a statement level counter. */ | ||
| 19655 | 114539152 | m_prebuilt->autoinc_last_value = 0; | |
| 19656 | |||
| 19657 | 114539152 | m_prebuilt->no_read_locking = false; | |
| 19658 | 114539152 | m_prebuilt->no_autoinc_locking = false; | |
| 19659 | |||
| 19660 | /* This transaction had called ha_innobase::start_stmt() */ | ||
| 19661 | 114539152 | trx_t *trx = m_prebuilt->trx; | |
| 19662 | |||
| 19663 |
4/6✓ Branch 0 taken 114292999 times.
✓ Branch 1 taken 246155 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114292805 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 114538960 times.
|
114539152 | if (!m_prebuilt->table->is_temporary() && trx != thd_to_trx(ha_thd())) { |
| 19664 | ✗ | ut_d(ut_error); | |
| 19665 | ut_o(return (0)); | ||
| 19666 | } | ||
| 19667 | |||
| 19668 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 114539034 times.
|
114538960 | ut_ad(!m_prebuilt->replace); |
| 19669 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 114539074 times.
|
114539034 | ut_ad(!m_prebuilt->on_duplicate_key_update); |
| 19670 | |||
| 19671 |
2/2✓ Branch 0 taken 2347621 times.
✓ Branch 1 taken 112191453 times.
|
114539074 | if (trx->lock.start_stmt) { |
| 19672 | 2347621 | trx->lock.start_stmt = false; | |
| 19673 | 2347621 | TrxInInnoDB::end_stmt(trx); | |
| 19674 | } | ||
| 19675 | |||
| 19676 | 114539133 | return (0); | |
| 19677 | } | ||
| 19678 | |||
| 19679 | /** | ||
| 19680 | MySQL calls this method at the end of each statement */ | ||
| 19681 | |||
| 19682 | 114538493 | int ha_innobase::reset() { return (end_stmt()); } | |
| 19683 | |||
| 19684 | /** MySQL calls this function at the start of each SQL statement inside LOCK | ||
| 19685 | TABLES. Inside LOCK TABLES the "::external_lock" method does not work to mark | ||
| 19686 | SQL statement borders. Note also a special case: if a temporary table is | ||
| 19687 | created inside LOCK TABLES, MySQL has not called external_lock() at all on | ||
| 19688 | that table. | ||
| 19689 | MySQL-5.0 also calls this before each statement in an execution of a stored | ||
| 19690 | procedure. To make the execution more deterministic for binlogging, MySQL-5.0 | ||
| 19691 | locks all tables involved in a stored procedure with full explicit table locks | ||
| 19692 | (thd_in_lock_tables(thd) holds in store_lock()) before executing the procedure. | ||
| 19693 | @param[in] thd handle to the user thread | ||
| 19694 | @param[in] lock_type lock type | ||
| 19695 | @return 0 or error code */ | ||
| 19696 | 2416600 | int ha_innobase::start_stmt(THD *thd, thr_lock_type lock_type) { | |
| 19697 | 2416600 | trx_t *trx = m_prebuilt->trx; | |
| 19698 | |||
| 19699 |
1/2✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
|
2416600 | DBUG_TRACE; |
| 19700 | |||
| 19701 |
1/2✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
|
2416600 | update_thd(thd); |
| 19702 | |||
| 19703 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2416600 times.
|
2416600 | ut_ad(m_prebuilt->table != nullptr); |
| 19704 | |||
| 19705 |
1/2✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
|
2416600 | TrxInInnoDB trx_in_innodb(trx); |
| 19706 | |||
| 19707 |
2/4✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2416600 times.
|
2416600 | if (m_prebuilt->table->is_intrinsic()) { |
| 19708 | ✗ | if (thd_sql_command(thd) == SQLCOM_ALTER_TABLE) { | |
| 19709 | ✗ | return HA_ERR_WRONG_COMMAND; | |
| 19710 | } | ||
| 19711 | |||
| 19712 | ✗ | return 0; | |
| 19713 | } | ||
| 19714 | |||
| 19715 | 2416600 | trx = m_prebuilt->trx; | |
| 19716 | |||
| 19717 |
1/2✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
|
2416600 | innobase_srv_conc_force_exit_innodb(trx); |
| 19718 | |||
| 19719 | /* Reset the AUTOINC statement level counter for multi-row INSERTs. */ | ||
| 19720 | 2416600 | trx->n_autoinc_rows = 0; | |
| 19721 | |||
| 19722 | 2416600 | m_prebuilt->sql_stat_start = true; | |
| 19723 | 2416600 | m_prebuilt->hint_need_to_fetch_extra_cols = 0; | |
| 19724 |
1/2✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
|
2416600 | reset_template(); |
| 19725 | |||
| 19726 |
7/8✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24988 times.
✓ Branch 3 taken 2391612 times.
✓ Branch 4 taken 24879 times.
✓ Branch 5 taken 109 times.
✓ Branch 6 taken 27 times.
✓ Branch 7 taken 2416573 times.
|
2441479 | if (m_prebuilt->table->is_temporary() && m_mysql_has_locked && |
| 19727 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 24852 times.
|
24879 | m_prebuilt->select_lock_type == LOCK_NONE) { |
| 19728 | dberr_t error; | ||
| 19729 | |||
| 19730 |
3/4✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 25 times.
|
27 | switch (thd_sql_command(thd)) { |
| 19731 | 2 | case SQLCOM_INSERT: | |
| 19732 | case SQLCOM_UPDATE: | ||
| 19733 | case SQLCOM_DELETE: | ||
| 19734 | case SQLCOM_REPLACE: | ||
| 19735 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | init_table_handle_for_HANDLER(); |
| 19736 | 2 | m_prebuilt->select_lock_type = LOCK_X; | |
| 19737 | 2 | m_stored_select_lock_type = LOCK_X; | |
| 19738 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | error = row_lock_table(m_prebuilt); |
| 19739 | |||
| 19740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (error != DB_SUCCESS) { |
| 19741 | ✗ | int st = convert_error_code_to_mysql(error, 0, thd); | |
| 19742 | ✗ | return st; | |
| 19743 | } | ||
| 19744 | 2 | break; | |
| 19745 | } | ||
| 19746 | } | ||
| 19747 | |||
| 19748 |
2/2✓ Branch 0 taken 109 times.
✓ Branch 1 taken 2416491 times.
|
2416600 | if (!m_mysql_has_locked) { |
| 19749 | /* This handle is for a temporary table created inside | ||
| 19750 | this same LOCK TABLES; since MySQL does NOT call external_lock | ||
| 19751 | in this case, we must use x-row locks inside InnoDB to be | ||
| 19752 | prepared for an update of a row */ | ||
| 19753 | |||
| 19754 | 109 | m_prebuilt->select_lock_type = LOCK_X; | |
| 19755 | |||
| 19756 |
2/2✓ Branch 0 taken 74550 times.
✓ Branch 1 taken 2341800 times.
|
2416350 | } else if ((trx->isolation_level != TRX_ISO_SERIALIZABLE && |
| 19757 |
7/8✓ Branch 0 taken 2416350 times.
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 74550 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65051 times.
✓ Branch 5 taken 9499 times.
✓ Branch 6 taken 9546 times.
✓ Branch 7 taken 2406945 times.
|
4898033 | lock_type == TL_READ && thd_sql_command(thd) == SQLCOM_SELECT) || |
| 19758 |
5/6✓ Branch 0 taken 2406992 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 543 times.
✓ Branch 3 taken 2406449 times.
✓ Branch 4 taken 393 times.
✓ Branch 5 taken 150 times.
|
2406992 | (trx->skip_gap_locks() && |
| 19759 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 356 times.
|
393 | (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && |
| 19760 |
3/4✓ Branch 0 taken 187 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 13 times.
|
187 | (thd_sql_command(thd) == SQLCOM_INSERT_SELECT || |
| 19761 |
3/4✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
✓ Branch 3 taken 4 times.
|
174 | thd_sql_command(thd) == SQLCOM_REPLACE_SELECT || |
| 19762 |
3/4✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
✓ Branch 3 taken 26 times.
|
170 | thd_sql_command(thd) == SQLCOM_UPDATE || |
| 19763 |
3/4✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 140 times.
|
144 | thd_sql_command(thd) == SQLCOM_CREATE_TABLE))) { |
| 19764 | /* For other than temporary tables, we obtain | ||
| 19765 | no lock for consistent read (plain SELECT). | ||
| 19766 | |||
| 19767 | If this session is using READ COMMITTED or READ | ||
| 19768 | UNCOMMITTED isolation level and MySQL is doing INSERT | ||
| 19769 | INTO... SELECT or REPLACE INTO...SELECT or UPDATE ... | ||
| 19770 | = (SELECT ...) or CREATE ... SELECT... without FOR | ||
| 19771 | UPDATE or IN SHARE MODE in select, then we use | ||
| 19772 | consistent read for select. | ||
| 19773 | |||
| 19774 | See also similar code in ha_innobase::store_lock(). */ | ||
| 19775 | |||
| 19776 | 9546 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 19777 | } else { | ||
| 19778 | /* Not a consistent read: restore the | ||
| 19779 | select_lock_type value. The value of | ||
| 19780 | stored_select_lock_type was decided in: | ||
| 19781 | 1) ::store_lock(), | ||
| 19782 | 2) ::external_lock(), | ||
| 19783 | 3) ::init_table_handle_for_HANDLER(). */ | ||
| 19784 | |||
| 19785 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2406945 times.
|
2406945 | ut_a(m_stored_select_lock_type != LOCK_NONE_UNSET); |
| 19786 | |||
| 19787 | 2406945 | m_prebuilt->select_lock_type = m_stored_select_lock_type; | |
| 19788 | } | ||
| 19789 | |||
| 19790 | 2416600 | *trx->detailed_error = 0; | |
| 19791 | |||
| 19792 |
1/2✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
|
2416600 | innobase_register_trx(ht, thd, trx); |
| 19793 | |||
| 19794 |
3/4✓ Branch 0 taken 2416600 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84643 times.
✓ Branch 3 taken 2331957 times.
|
2416600 | if (!trx_is_started(trx)) { |
| 19795 | 84643 | ++trx->will_lock; | |
| 19796 | } | ||
| 19797 | |||
| 19798 | /* Only do it once per transaction. */ | ||
| 19799 |
4/4✓ Branch 0 taken 2347622 times.
✓ Branch 1 taken 68978 times.
✓ Branch 2 taken 2347621 times.
✓ Branch 3 taken 1 times.
|
2416600 | if (!trx->lock.start_stmt && lock_type != TL_UNLOCK) { |
| 19800 | 2347621 | trx->lock.start_stmt = true; | |
| 19801 |
1/2✓ Branch 0 taken 2347621 times.
✗ Branch 1 not taken.
|
2347621 | TrxInInnoDB::begin_stmt(trx); |
| 19802 | } | ||
| 19803 | |||
| 19804 | 2416600 | return 0; | |
| 19805 | 2416600 | } | |
| 19806 | |||
| 19807 | 111541533 | trx_t::isolation_level_t innobase_trx_map_isolation_level( | |
| 19808 | enum_tx_isolation iso) { | ||
| 19809 | trx_t::isolation_level_t trx_isolation_level; | ||
| 19810 | |||
| 19811 |
4/5✓ Branch 0 taken 32781337 times.
✓ Branch 1 taken 67817758 times.
✓ Branch 2 taken 20212 times.
✓ Branch 3 taken 10922425 times.
✗ Branch 4 not taken.
|
111541533 | switch (iso) { |
| 19812 | 32781337 | case ISO_REPEATABLE_READ: | |
| 19813 | 32781337 | trx_isolation_level = TRX_ISO_REPEATABLE_READ; | |
| 19814 | 32781337 | break; | |
| 19815 | 67817758 | case ISO_READ_COMMITTED: | |
| 19816 | 67817758 | trx_isolation_level = TRX_ISO_READ_COMMITTED; | |
| 19817 | 67817758 | break; | |
| 19818 | 20212 | case ISO_SERIALIZABLE: | |
| 19819 | 20212 | trx_isolation_level = TRX_ISO_SERIALIZABLE; | |
| 19820 | 20212 | break; | |
| 19821 | 10922425 | case ISO_READ_UNCOMMITTED: | |
| 19822 | 10922425 | trx_isolation_level = TRX_ISO_READ_UNCOMMITTED; | |
| 19823 | 10922425 | break; | |
| 19824 | ✗ | default: | |
| 19825 | ✗ | ut_error; | |
| 19826 | } | ||
| 19827 | |||
| 19828 | 111541732 | return trx_isolation_level; | |
| 19829 | } | ||
| 19830 | |||
| 19831 | /** As MySQL will execute an external lock for every new table it uses when it | ||
| 19832 | starts to process an SQL statement (an exception is when MySQL calls | ||
| 19833 | start_stmt for the handle) we can use this function to store the pointer to | ||
| 19834 | the THD in the handle. We will also use this function to communicate | ||
| 19835 | to InnoDB that a new SQL statement has started and that we must store a | ||
| 19836 | savepoint to our transaction handle, so that we are able to roll back | ||
| 19837 | the SQL statement in case of an error. | ||
| 19838 | @return 0 */ | ||
| 19839 | |||
| 19840 | 224390678 | int ha_innobase::external_lock(THD *thd, /*!< in: handle to the user thread */ | |
| 19841 | int lock_type) /*!< in: lock type */ | ||
| 19842 | { | ||
| 19843 |
1/2✓ Branch 0 taken 224392416 times.
✗ Branch 1 not taken.
|
224390678 | DBUG_TRACE; |
| 19844 |
5/8✓ Branch 0 taken 224391927 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224392202 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12050 times.
✓ Branch 5 taken 224380152 times.
✓ Branch 6 taken 12050 times.
✗ Branch 7 not taken.
|
224392416 | DBUG_PRINT("enter", ("lock_type: %d", lock_type)); |
| 19845 | |||
| 19846 |
1/2✓ Branch 0 taken 224392495 times.
✗ Branch 1 not taken.
|
224392202 | update_thd(thd); |
| 19847 | |||
| 19848 | 224392495 | trx_t *trx = m_prebuilt->trx; | |
| 19849 | |||
| 19850 |
1/2✓ Branch 0 taken 224392238 times.
✗ Branch 1 not taken.
|
224392495 | enum_sql_command sql_command = (enum_sql_command)thd_sql_command(thd); |
| 19851 | |||
| 19852 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 224392288 times.
|
224392238 | ut_ad(m_prebuilt->table); |
| 19853 | |||
| 19854 |
2/4✓ Branch 0 taken 224392180 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 224392180 times.
|
224392288 | if (m_prebuilt->table->is_intrinsic()) { |
| 19855 | ✗ | if (sql_command == SQLCOM_ALTER_TABLE) { | |
| 19856 | ✗ | return HA_ERR_WRONG_COMMAND; | |
| 19857 | } | ||
| 19858 | |||
| 19859 | ✗ | TrxInInnoDB::begin_stmt(trx); | |
| 19860 | |||
| 19861 | ✗ | return 0; | |
| 19862 | } | ||
| 19863 | |||
| 19864 | /* Statement based binlogging does not work in isolation level | ||
| 19865 | READ UNCOMMITTED and READ COMMITTED since the necessary | ||
| 19866 | locks cannot be taken. In this case, we print an | ||
| 19867 | informative error message and return with an error. | ||
| 19868 | Note: decide_logging_format would give the same error message, | ||
| 19869 | except it cannot give the extra details. */ | ||
| 19870 | |||
| 19871 |
3/4✓ Branch 0 taken 29214887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 471280 times.
✓ Branch 3 taken 28743607 times.
|
29214816 | if (lock_type == F_WRLCK && !(table_flags() & HA_BINLOG_STMT_CAPABLE) && |
| 19872 |
3/4✓ Branch 0 taken 471251 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8667 times.
✓ Branch 3 taken 462584 times.
|
471280 | thd_binlog_format(thd) == BINLOG_FORMAT_STMT && |
| 19873 |
10/12✓ Branch 0 taken 29214816 times.
✓ Branch 1 taken 195177364 times.
✓ Branch 2 taken 8667 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8663 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 8663 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 23 times.
✓ Branch 9 taken 8640 times.
✓ Branch 10 taken 23 times.
✓ Branch 11 taken 224392199 times.
|
253607038 | thd_binlog_filter_ok(thd) && thd_sqlcom_can_generate_row_events(thd)) { |
| 19874 | 23 | bool skip = false; | |
| 19875 | |||
| 19876 | /* used by test case */ | ||
| 19877 |
2/4✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
|
23 | DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = true;); |
| 19878 | |||
| 19879 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | if (!skip) { |
| 19880 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), |
| 19881 | " InnoDB is limited to row-logging when" | ||
| 19882 | " transaction isolation level is" | ||
| 19883 | " READ COMMITTED or READ UNCOMMITTED."); | ||
| 19884 | |||
| 19885 | 23 | return HA_ERR_LOGGING_IMPOSSIBLE; | |
| 19886 | } | ||
| 19887 | } | ||
| 19888 | |||
| 19889 | /* Check for UPDATEs in read-only mode. */ | ||
| 19890 |
4/4✓ Branch 0 taken 150361 times.
✓ Branch 1 taken 224241838 times.
✓ Branch 2 taken 150051 times.
✓ Branch 3 taken 310 times.
|
224392199 | if (srv_read_only_mode && |
| 19891 |
4/4✓ Branch 0 taken 149733 times.
✓ Branch 1 taken 318 times.
✓ Branch 2 taken 149732 times.
✓ Branch 3 taken 1 times.
|
150051 | (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT || |
| 19892 |
2/4✓ Branch 0 taken 149732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149732 times.
✗ Branch 3 not taken.
|
149732 | sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE || |
| 19893 |
2/4✓ Branch 0 taken 149732 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 149732 times.
|
149732 | sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || |
| 19894 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 149732 times.
✗ Branch 3 not taken.
|
149732 | (sql_command == SQLCOM_CREATE_TABLE && lock_type == F_WRLCK) || |
| 19895 |
3/4✓ Branch 0 taken 149732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149429 times.
✓ Branch 3 taken 303 times.
|
149732 | sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX || |
| 19896 |
2/2✓ Branch 0 taken 149426 times.
✓ Branch 1 taken 3 times.
|
149429 | sql_command == SQLCOM_DELETE || |
| 19897 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 149422 times.
|
149426 | sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY || |
| 19898 | sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) { | ||
| 19899 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 939 times.
|
939 | if (sql_command == SQLCOM_CREATE_TABLE) { |
| 19900 | ✗ | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_INNODB_READ_ONLY); | |
| 19901 | ✗ | return HA_ERR_INNODB_READ_ONLY; | |
| 19902 | } else { | ||
| 19903 |
1/2✓ Branch 0 taken 939 times.
✗ Branch 1 not taken.
|
939 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 19904 | 939 | return HA_ERR_TABLE_READONLY; | |
| 19905 | } | ||
| 19906 | } | ||
| 19907 | |||
| 19908 | 224391260 | m_prebuilt->sql_stat_start = true; | |
| 19909 | 224391260 | m_prebuilt->hint_need_to_fetch_extra_cols = 0; | |
| 19910 | |||
| 19911 |
1/2✓ Branch 0 taken 224390480 times.
✗ Branch 1 not taken.
|
224391260 | reset_template(); |
| 19912 | |||
| 19913 |
3/4✓ Branch 0 taken 454 times.
✓ Branch 1 taken 466 times.
✓ Branch 2 taken 224389796 times.
✗ Branch 3 not taken.
|
224390480 | switch (m_prebuilt->table->quiesce) { |
| 19914 | 454 | case QUIESCE_START: | |
| 19915 | /* Check for FLUSH TABLE t WITH READ LOCK; */ | ||
| 19916 |
3/6✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 454 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 454 times.
✗ Branch 5 not taken.
|
454 | if (!srv_read_only_mode && sql_command == SQLCOM_FLUSH && |
| 19917 | lock_type == F_RDLCK) { | ||
| 19918 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 452 times.
|
454 | if (dict_table_is_discarded(m_prebuilt->table)) { |
| 19919 | 2 | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, | |
| 19920 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ER_TABLESPACE_DISCARDED, table->s->table_name.str); |
| 19921 | |||
| 19922 | 2 | return HA_ERR_NO_SUCH_TABLE; | |
| 19923 | } | ||
| 19924 | |||
| 19925 |
1/2✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
|
452 | row_quiesce_table_start(m_prebuilt->table, trx); |
| 19926 | |||
| 19927 | /* Use the transaction instance to track UNLOCK | ||
| 19928 | TABLES. It can be done via START TRANSACTION; too | ||
| 19929 | implicitly. */ | ||
| 19930 | |||
| 19931 | 452 | ++trx->flush_tables; | |
| 19932 | } | ||
| 19933 | 452 | break; | |
| 19934 | |||
| 19935 | 466 | case QUIESCE_COMPLETE: | |
| 19936 | /* Check for UNLOCK TABLES; implicit or explicit | ||
| 19937 | or trx interruption. */ | ||
| 19938 |
6/6✓ Branch 0 taken 456 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 452 times.
✓ Branch 4 taken 452 times.
✓ Branch 5 taken 14 times.
|
470 | if (trx->flush_tables > 0 && |
| 19939 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | (lock_type == F_UNLCK || trx_is_interrupted(trx))) { |
| 19940 |
1/2✓ Branch 0 taken 452 times.
✗ Branch 1 not taken.
|
452 | row_quiesce_table_complete(m_prebuilt->table, trx); |
| 19941 | |||
| 19942 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
|
452 | ut_a(trx->flush_tables > 0); |
| 19943 | 452 | --trx->flush_tables; | |
| 19944 | } | ||
| 19945 | |||
| 19946 | 466 | break; | |
| 19947 | |||
| 19948 | 224389796 | case QUIESCE_NONE: | |
| 19949 | 224389796 | break; | |
| 19950 | } | ||
| 19951 | |||
| 19952 |
2/2✓ Branch 0 taken 29213439 times.
✓ Branch 1 taken 195177039 times.
|
224390478 | if (lock_type == F_WRLCK) { |
| 19953 | /* If this is a SELECT, then it is in UPDATE TABLE ... | ||
| 19954 | or SELECT ... FOR UPDATE */ | ||
| 19955 | 29213439 | m_prebuilt->select_lock_type = LOCK_X; | |
| 19956 | 29213439 | m_stored_select_lock_type = LOCK_X; | |
| 19957 | } | ||
| 19958 | |||
| 19959 |
5/6✓ Branch 0 taken 82982763 times.
✓ Branch 1 taken 141407715 times.
✓ Branch 2 taken 82982763 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 127 times.
✓ Branch 5 taken 224390369 times.
|
224390478 | ut_ad(!(lock_type == F_RDLCK && m_prebuilt->select_lock_type == LOCK_X)); |
| 19960 | |||
| 19961 |
2/2✓ Branch 0 taken 112196294 times.
✓ Branch 1 taken 112194075 times.
|
224390369 | if (lock_type != F_UNLCK) { |
| 19962 | /* MySQL is setting a new table lock */ | ||
| 19963 | |||
| 19964 | 112196294 | *trx->detailed_error = 0; | |
| 19965 | |||
| 19966 |
1/2✓ Branch 0 taken 112196289 times.
✗ Branch 1 not taken.
|
112196294 | innobase_register_trx(ht, thd, trx); |
| 19967 | |||
| 19968 | /* | ||
| 19969 | For reads we will use LOCK_NONE, LOCK_S or LOCK_X according to this chart: | ||
| 19970 | +-----------------------------------------+ | ||
| 19971 | | is_dd_table or skip_locking | | ||
| 19972 | +----------------------------------+------+ | ||
| 19973 | | false | true | | ||
| 19974 | +----------------------------------| | | ||
| 19975 | | TRANSACTION ISOLATION LEVEL | | | ||
| 19976 | +----------------+-----------------+ | | ||
| 19977 | | < SERIALIZABLE | = SERIALIZABLE | | | ||
| 19978 | +--------------------+----------------+-----------------+------+ | ||
| 19979 | | non-locking SELECT | NONE [1] | S [3] | NONE | | ||
| 19980 | | SELECT FOR SHARE | S [2] | S | NONE | | ||
| 19981 | | SELECT FOR UPDATE | X | X | X | | ||
| 19982 | +--------------------+----------------+-----------------+------+ | ||
| 19983 | Where LOCK_NONE means a non-locking consistent reads via read-view, and | ||
| 19984 | `no_read_locking` is set to `true` by Server calling | ||
| 19985 | ha_extra(). | ||
| 19986 | Notes: | ||
| 19987 | [1,2] The server layer calls external_lock(..,F_RDLCK) which retains the old | ||
| 19988 | value of select_lock_type before the call. In most cases it is the value | ||
| 19989 | set by a previous call to store_lock(..): | ||
| 19990 | [1] For a non-locking SELECT the Server layer calls store_lock(..,TL_READ) | ||
| 19991 | which sets select_lock_type = LOCK_NONE, except for ACL tables which | ||
| 19992 | treat it as in [1]. | ||
| 19993 | [2] In case of SELECT FOR SHARE the Server layer calls | ||
| 19994 | store_lock(..,TL_READ_WITH_SHARED_LOCKS) which sets | ||
| 19995 | select_lock_type = LOCK_S | ||
| 19996 | [3] An exception is consistent reads in the AUTOCOMMIT=1 mode: | ||
| 19997 | we know that they are read-only transactions, and they can be serialized | ||
| 19998 | also if performed as consistent reads. Thus we use LOCK_NONE for them. | ||
| 19999 | |||
| 20000 | For non-SELECT commands, there may be still possibility of setting | ||
| 20001 | skip_locking=1. E.g., | ||
| 20002 | - UPDATE ... WHERE ... (SELECT... acl_table); | ||
| 20003 | - DELETE ... WHERE ... (SELECT... acl_table); | ||
| 20004 | The first entry 'non-locking SELECT' in above table applies in these case. | ||
| 20005 | */ | ||
| 20006 |
2/2✓ Branch 0 taken 82982856 times.
✓ Branch 1 taken 29213433 times.
|
112196289 | if (lock_type == F_RDLCK) { |
| 20007 | /** | ||
| 20008 | To limit range of circumstances under which transaction's isolation | ||
| 20009 | level can be compromised, we allow disabling readlocks only for DD | ||
| 20010 | and ACL tables. | ||
| 20011 | */ | ||
| 20012 |
8/10✓ Branch 0 taken 2301425 times.
✓ Branch 1 taken 80681431 times.
✓ Branch 2 taken 22734 times.
✓ Branch 3 taken 2278691 times.
✓ Branch 4 taken 22734 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 22734 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 82982808 times.
|
82982856 | ut_ad(!m_prebuilt->no_read_locking || m_prebuilt->table->is_dd_table || |
| 20013 | is_acl_table(table)); | ||
| 20014 | |||
| 20015 |
4/4✓ Branch 0 taken 2553828 times.
✓ Branch 1 taken 80428980 times.
✓ Branch 2 taken 22735 times.
✓ Branch 3 taken 2531093 times.
|
82982808 | if (m_prebuilt->table->is_dd_table || m_prebuilt->no_read_locking) { |
| 20016 | 80451715 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 20017 | 80451715 | m_stored_select_lock_type = LOCK_NONE; | |
| 20018 | 5063585 | } else if (trx->isolation_level == TRX_ISO_SERIALIZABLE && | |
| 20019 |
6/6✓ Branch 0 taken 1399 times.
✓ Branch 1 taken 2529694 times.
✓ Branch 2 taken 327 times.
✓ Branch 3 taken 1072 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 2531066 times.
|
2531420 | m_prebuilt->select_lock_type == LOCK_NONE && |
| 20020 |
3/4✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 300 times.
|
327 | thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 20021 | 27 | m_prebuilt->select_lock_type = LOCK_S; | |
| 20022 | 27 | m_stored_select_lock_type = LOCK_S; | |
| 20023 | } else { | ||
| 20024 | // Retain value set earlier for example via store_lock() | ||
| 20025 | // which is LOCK_S or LOCK_NONE | ||
| 20026 |
4/6✓ Branch 0 taken 1302037 times.
✓ Branch 1 taken 1229029 times.
✓ Branch 2 taken 1302037 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2531068 times.
|
2531066 | ut_ad(m_prebuilt->select_lock_type == LOCK_S || |
| 20027 | m_prebuilt->select_lock_type == LOCK_NONE); | ||
| 20028 | } | ||
| 20029 | } | ||
| 20030 | |||
| 20031 | /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK | ||
| 20032 | TABLES if AUTOCOMMIT=1. It does not make much sense to acquire | ||
| 20033 | an InnoDB table lock if it is released immediately at the end | ||
| 20034 | of LOCK TABLES, and InnoDB's table locks in that case cause | ||
| 20035 | VERY easily deadlocks. | ||
| 20036 | |||
| 20037 | We do not set InnoDB table locks if user has not explicitly | ||
| 20038 | requested a table lock. Note that thd_in_lock_tables(thd) | ||
| 20039 | can hold in some cases, e.g., at the start of a stored | ||
| 20040 | procedure call (SQLCOM_CALL). */ | ||
| 20041 | |||
| 20042 |
2/2✓ Branch 0 taken 30442353 times.
✓ Branch 1 taken 81753890 times.
|
112196243 | if (m_prebuilt->select_lock_type != LOCK_NONE) { |
| 20043 |
3/4✓ Branch 0 taken 3259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3257 times.
✓ Branch 3 taken 2 times.
|
3259 | if (sql_command == SQLCOM_LOCK_TABLES && THDVAR(thd, table_locks) && |
| 20044 |
7/8✓ Branch 0 taken 3259 times.
✓ Branch 1 taken 30439094 times.
✓ Branch 2 taken 3257 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 151 times.
✓ Branch 5 taken 3106 times.
✓ Branch 6 taken 151 times.
✓ Branch 7 taken 30442202 times.
|
30445763 | thd_test_options(thd, OPTION_NOT_AUTOCOMMIT) && |
| 20045 |
2/4✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 151 times.
✗ Branch 3 not taken.
|
151 | thd_in_lock_tables(thd)) { |
| 20046 |
1/2✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
|
151 | dberr_t error = row_lock_table(m_prebuilt); |
| 20047 | |||
| 20048 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 151 times.
|
151 | if (error != DB_SUCCESS) { |
| 20049 | ✗ | return convert_error_code_to_mysql(error, 0, thd); | |
| 20050 | } | ||
| 20051 | } | ||
| 20052 | |||
| 20053 | 30442353 | trx->mysql_n_tables_locked++; | |
| 20054 | } | ||
| 20055 | |||
| 20056 | 112196243 | trx->n_mysql_tables_in_use++; | |
| 20057 | 112196243 | m_mysql_has_locked = true; | |
| 20058 | |||
| 20059 |
7/8✓ Branch 0 taken 112196505 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91118357 times.
✓ Branch 3 taken 21078148 times.
✓ Branch 4 taken 81459155 times.
✓ Branch 5 taken 9659202 times.
✓ Branch 6 taken 9659382 times.
✓ Branch 7 taken 102537123 times.
|
193655398 | if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE || |
| 20060 |
2/2✓ Branch 0 taken 374 times.
✓ Branch 1 taken 81458781 times.
|
81459155 | m_stored_select_lock_type != LOCK_NONE)) { |
| 20061 | 9659382 | ++trx->will_lock; | |
| 20062 | } | ||
| 20063 | |||
| 20064 |
1/2✓ Branch 0 taken 112196779 times.
✗ Branch 1 not taken.
|
112196505 | TrxInInnoDB::begin_stmt(trx); |
| 20065 | |||
| 20066 | #ifdef UNIV_DEBUG | ||
| 20067 |
6/8✓ Branch 0 taken 112196795 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112196564 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 78243515 times.
✓ Branch 5 taken 33953049 times.
✓ Branch 6 taken 78243525 times.
✓ Branch 7 taken 33953023 times.
|
112196779 | if (thd != nullptr && thd_tx_is_dd_trx(thd)) { |
| 20068 | 78243525 | trx->is_dd_trx = true; | |
| 20069 | } | ||
| 20070 | #endif /* UNIV_DEBUG */ | ||
| 20071 | 112196548 | return 0; | |
| 20072 | } else { | ||
| 20073 |
1/2✓ Branch 0 taken 112194222 times.
✗ Branch 1 not taken.
|
112194075 | TrxInInnoDB::end_stmt(trx); |
| 20074 | |||
| 20075 |
3/4✓ Branch 0 taken 101809279 times.
✓ Branch 1 taken 10384943 times.
✓ Branch 2 taken 101809638 times.
✗ Branch 3 not taken.
|
112194222 | DEBUG_SYNC_C("ha_innobase_end_statement"); |
| 20076 | } | ||
| 20077 | |||
| 20078 | /* MySQL is releasing a table lock */ | ||
| 20079 | |||
| 20080 | 112194581 | trx->n_mysql_tables_in_use--; | |
| 20081 | 112194581 | m_mysql_has_locked = false; | |
| 20082 | |||
| 20083 |
1/2✓ Branch 0 taken 112194422 times.
✗ Branch 1 not taken.
|
112194581 | innobase_srv_conc_force_exit_innodb(trx); |
| 20084 | |||
| 20085 | /* If the MySQL lock count drops to zero we know that the current SQL | ||
| 20086 | statement has ended */ | ||
| 20087 | |||
| 20088 |
2/2✓ Branch 0 taken 35504711 times.
✓ Branch 1 taken 76689711 times.
|
112194422 | if (trx->n_mysql_tables_in_use == 0) { |
| 20089 | 35504711 | trx->mysql_n_tables_locked = 0; | |
| 20090 | 35504711 | m_prebuilt->used_in_HANDLER = false; | |
| 20091 | |||
| 20092 |
3/4✓ Branch 0 taken 35504689 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20516088 times.
✓ Branch 3 taken 14988601 times.
|
35504711 | if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { |
| 20093 |
3/4✓ Branch 0 taken 20515887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 626612 times.
✓ Branch 3 taken 19889275 times.
|
20516088 | if (trx_is_started(trx)) { |
| 20094 |
1/2✓ Branch 0 taken 626611 times.
✗ Branch 1 not taken.
|
626612 | innobase_commit(ht, thd, true); |
| 20095 | } else { | ||
| 20096 | /* Since the trx state is TRX_NOT_STARTED, | ||
| 20097 | trx_commit() will not be called. Reset | ||
| 20098 | trx->is_dd_trx here */ | ||
| 20099 | 19889275 | ut_d(trx->is_dd_trx = false); | |
| 20100 | } | ||
| 20101 | |||
| 20102 |
4/4✓ Branch 0 taken 373790 times.
✓ Branch 1 taken 14614811 times.
✓ Branch 2 taken 2354 times.
✓ Branch 3 taken 14986245 times.
|
15362389 | } else if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && |
| 20103 |
3/4✓ Branch 0 taken 373788 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2354 times.
✓ Branch 3 taken 371434 times.
|
373790 | MVCC::is_view_active(trx->read_view)) { |
| 20104 |
1/2✓ Branch 0 taken 2354 times.
✗ Branch 1 not taken.
|
2354 | mutex_enter(&trx_sys->mutex); |
| 20105 | |||
| 20106 |
1/2✓ Branch 0 taken 2354 times.
✗ Branch 1 not taken.
|
2354 | trx_sys->mvcc->view_close(trx->read_view, true); |
| 20107 | |||
| 20108 |
1/2✓ Branch 0 taken 2354 times.
✗ Branch 1 not taken.
|
2354 | mutex_exit(&trx_sys->mutex); |
| 20109 | } | ||
| 20110 | } | ||
| 20111 | |||
| 20112 |
5/8✓ Branch 0 taken 112193821 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83714605 times.
✓ Branch 3 taken 28479216 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 83714605 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 112193821 times.
|
112194196 | if (!trx_is_started(trx) && lock_type != F_UNLCK && |
| 20113 | ✗ | (m_prebuilt->select_lock_type != LOCK_NONE || | |
| 20114 | ✗ | m_stored_select_lock_type != LOCK_NONE)) { | |
| 20115 | ✗ | ++trx->will_lock; | |
| 20116 | } | ||
| 20117 | |||
| 20118 | 112193821 | return 0; | |
| 20119 | 224391333 | } | |
| 20120 | |||
| 20121 | /** Here we export InnoDB status variables to MySQL. */ | ||
| 20122 | 107957 | static void innodb_export_status() { | |
| 20123 |
1/2✓ Branch 0 taken 107957 times.
✗ Branch 1 not taken.
|
107957 | if (innodb_inited) { |
| 20124 | 107957 | srv_export_innodb_status(); | |
| 20125 | } | ||
| 20126 | 107954 | } | |
| 20127 | |||
| 20128 | /** Implements the SHOW ENGINE INNODB STATUS command. Sends the output of the | ||
| 20129 | InnoDB Monitor to the client. | ||
| 20130 | @param[in] hton the innodb handlerton | ||
| 20131 | @param[in] thd the MySQL query thread of the caller | ||
| 20132 | @param[in] stat_print print function | ||
| 20133 | @return 0 on success */ | ||
| 20134 | 41 | static int innodb_show_status(handlerton *hton, THD *thd, | |
| 20135 | stat_print_fn *stat_print) { | ||
| 20136 | static const char truncated_msg[] = "... truncated...\n"; | ||
| 20137 | 41 | const long MAX_STATUS_SIZE = 1048576; | |
| 20138 | 41 | ulint trx_list_start = ULINT_UNDEFINED; | |
| 20139 | 41 | ulint trx_list_end = ULINT_UNDEFINED; | |
| 20140 | bool ret_val; | ||
| 20141 | |||
| 20142 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | DBUG_TRACE; |
| 20143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | assert(hton == innodb_hton_ptr); |
| 20144 | |||
| 20145 | /* We don't create the temp files or associated | ||
| 20146 | mutexes in read-only-mode */ | ||
| 20147 | |||
| 20148 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (srv_read_only_mode) { |
| 20149 | ✗ | return 0; | |
| 20150 | } | ||
| 20151 | |||
| 20152 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | trx_t *trx = check_trx_exists(thd); |
| 20153 | |||
| 20154 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | innobase_srv_conc_force_exit_innodb(trx); |
| 20155 | |||
| 20156 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | TrxInInnoDB trx_in_innodb(trx); |
| 20157 | |||
| 20158 | /* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE | ||
| 20159 | bytes of text. */ | ||
| 20160 | |||
| 20161 | char *str; | ||
| 20162 | ssize_t flen; | ||
| 20163 | |||
| 20164 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | mutex_enter(&srv_monitor_file_mutex); |
| 20165 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | rewind(srv_monitor_file); |
| 20166 | |||
| 20167 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | srv_printf_innodb_monitor(srv_monitor_file, false, &trx_list_start, |
| 20168 | &trx_list_end); | ||
| 20169 | |||
| 20170 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | os_file_set_eof(srv_monitor_file); |
| 20171 | |||
| 20172 |
2/4✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41 times.
|
41 | if ((flen = ftell(srv_monitor_file)) < 0) { |
| 20173 | ✗ | flen = 0; | |
| 20174 | } | ||
| 20175 | |||
| 20176 | ssize_t usable_len; | ||
| 20177 | |||
| 20178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (flen > MAX_STATUS_SIZE) { |
| 20179 | ✗ | usable_len = MAX_STATUS_SIZE; | |
| 20180 | ✗ | srv_truncated_status_writes++; | |
| 20181 | } else { | ||
| 20182 | 41 | usable_len = flen; | |
| 20183 | } | ||
| 20184 | |||
| 20185 | /* allocate buffer for the string, and | ||
| 20186 | read the contents of the temporary file */ | ||
| 20187 | |||
| 20188 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | str = (char *)my_malloc(PSI_INSTRUMENT_ME, usable_len + 1, MYF(0)); |
| 20189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (!str) { |
| 20190 | ✗ | mutex_exit(&srv_monitor_file_mutex); | |
| 20191 | ✗ | return 1; | |
| 20192 | } | ||
| 20193 | |||
| 20194 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | rewind(srv_monitor_file); |
| 20195 | |||
| 20196 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | if (flen < MAX_STATUS_SIZE) { |
| 20197 | /* Display the entire output. */ | ||
| 20198 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | flen = fread(str, 1, flen, srv_monitor_file); |
| 20199 | ✗ | } else if (trx_list_end < (ulint)flen && trx_list_start < trx_list_end && | |
| 20200 | ✗ | trx_list_start + (flen - trx_list_end) < | |
| 20201 | MAX_STATUS_SIZE - sizeof truncated_msg - 1) { | ||
| 20202 | /* Omit the beginning of the list of active transactions. */ | ||
| 20203 | ✗ | ssize_t len = fread(str, 1, trx_list_start, srv_monitor_file); | |
| 20204 | |||
| 20205 | ✗ | memcpy(str + len, truncated_msg, sizeof truncated_msg - 1); | |
| 20206 | ✗ | len += sizeof truncated_msg - 1; | |
| 20207 | ✗ | usable_len = (MAX_STATUS_SIZE - 1) - len; | |
| 20208 | ✗ | fseek(srv_monitor_file, static_cast<long>(flen - usable_len), SEEK_SET); | |
| 20209 | ✗ | len += fread(str + len, 1, usable_len, srv_monitor_file); | |
| 20210 | ✗ | flen = len; | |
| 20211 | ✗ | } else { | |
| 20212 | /* Omit the end of the output. */ | ||
| 20213 | ✗ | flen = fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file); | |
| 20214 | } | ||
| 20215 | |||
| 20216 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | mutex_exit(&srv_monitor_file_mutex); |
| 20217 | |||
| 20218 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | ret_val = stat_print(thd, innobase_hton_name, |
| 20219 | static_cast<uint>(strlen(innobase_hton_name)), | ||
| 20220 | STRING_WITH_LEN(""), str, static_cast<uint>(flen)); | ||
| 20221 | |||
| 20222 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | my_free(str); |
| 20223 | |||
| 20224 | 41 | return ret_val; | |
| 20225 | 41 | } | |
| 20226 | |||
| 20227 | /** Implements Log_resource lock. | ||
| 20228 | @param[in] hton the innodb handlerton | ||
| 20229 | @return false on success */ | ||
| 20230 | 26 | static bool innobase_lock_hton_log(handlerton *hton) { | |
| 20231 | 26 | bool ret_val = false; | |
| 20232 | |||
| 20233 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | DBUG_TRACE; |
| 20234 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
|
26 | assert(hton == innodb_hton_ptr); |
| 20235 | |||
| 20236 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | log_position_lock(*log_sys); |
| 20237 | |||
| 20238 | 26 | return ret_val; | |
| 20239 | 26 | } | |
| 20240 | |||
| 20241 | /** Implements Log_resource unlock. | ||
| 20242 | @param[in] hton the innodb handlerton | ||
| 20243 | @return false on success */ | ||
| 20244 | 26 | static bool innobase_unlock_hton_log(handlerton *hton) { | |
| 20245 | 26 | bool ret_val = false; | |
| 20246 | |||
| 20247 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | DBUG_TRACE; |
| 20248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
|
26 | assert(hton == innodb_hton_ptr); |
| 20249 | |||
| 20250 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | log_position_unlock(*log_sys); |
| 20251 | |||
| 20252 | 26 | return ret_val; | |
| 20253 | 26 | } | |
| 20254 | |||
| 20255 | /** Implements Log_resource collect_info. | ||
| 20256 | @param[in] hton the innodb handlerton | ||
| 20257 | @param[in] json the JSON dom to receive the log info | ||
| 20258 | @return false on success */ | ||
| 20259 | 25 | static bool innobase_collect_hton_log_info(handlerton *hton, Json_dom *json) { | |
| 20260 | 25 | bool ret_val = false; | |
| 20261 | lsn_t lsn; | ||
| 20262 | lsn_t lsn_checkpoint; | ||
| 20263 | |||
| 20264 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | DBUG_TRACE; |
| 20265 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | assert(hton == innodb_hton_ptr); |
| 20266 | |||
| 20267 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | log_position_collect_lsn_info(*log_sys, &lsn, &lsn_checkpoint); |
| 20268 | |||
| 20269 | 25 | Json_object *json_engines = static_cast<Json_object *>(json); | |
| 20270 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | Json_object json_innodb; |
| 20271 | 25 | Json_int json_lsn(lsn); | |
| 20272 | 25 | Json_int json_lsn_checkpoint(lsn_checkpoint); | |
| 20273 | |||
| 20274 |
2/4✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
|
25 | ret_val = json_innodb.add_clone("LSN", &json_lsn); |
| 20275 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | if (!ret_val) |
| 20276 |
2/4✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
|
25 | ret_val = json_innodb.add_clone("LSN_checkpoint", &json_lsn_checkpoint); |
| 20277 |
3/6✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
|
25 | if (!ret_val) ret_val = json_engines->add_clone("InnoDB", &json_innodb); |
| 20278 | |||
| 20279 | 25 | return ret_val; | |
| 20280 | 25 | } | |
| 20281 | |||
| 20282 | /** Callback for collecting mutex statistics */ | ||
| 20283 | struct ShowStatus { | ||
| 20284 | /** For tracking the mutex metrics */ | ||
| 20285 | struct Value { | ||
| 20286 | /** Constructor | ||
| 20287 | @param[in] name Name of the mutex | ||
| 20288 | @param[in] spins Number of spins | ||
| 20289 | @param[in] waits OS waits so far | ||
| 20290 | @param[in] calls Number of calls to enter() */ | ||
| 20291 | ✗ | Value(const char *name, ulint spins, uint64_t waits, uint64_t calls) | |
| 20292 | ✗ | : m_name(name), m_spins(spins), m_waits(waits), m_calls(calls) { | |
| 20293 | /* No op */ | ||
| 20294 | } | ||
| 20295 | |||
| 20296 | /** Mutex name */ | ||
| 20297 | std::string m_name; | ||
| 20298 | |||
| 20299 | /** Spins so far */ | ||
| 20300 | ulint m_spins; | ||
| 20301 | |||
| 20302 | /** Waits so far */ | ||
| 20303 | uint64_t m_waits; | ||
| 20304 | |||
| 20305 | /** Number of calls so far */ | ||
| 20306 | uint64_t m_calls; | ||
| 20307 | }; | ||
| 20308 | |||
| 20309 | /** Order by m_waits, in descending order. */ | ||
| 20310 | struct OrderByWaits { | ||
| 20311 | /** @return true if rhs < lhs */ | ||
| 20312 | ✗ | bool operator()(const Value &lhs, const Value &rhs) const UNIV_NOTHROW { | |
| 20313 | ✗ | return (rhs.m_waits < lhs.m_waits); | |
| 20314 | } | ||
| 20315 | }; | ||
| 20316 | |||
| 20317 | typedef std::vector<Value, ut::allocator<Value>> Values; | ||
| 20318 | |||
| 20319 | /** Collect the individual latch counts */ | ||
| 20320 | struct GetCount { | ||
| 20321 | typedef latch_meta_t::CounterType::Count Count; | ||
| 20322 | |||
| 20323 | /** Constructor | ||
| 20324 | @param[in] name Latch name | ||
| 20325 | @param[in,out] values Put the values here */ | ||
| 20326 | 726 | GetCount(const char *name, Values *values) UNIV_NOTHROW : m_name(name), | |
| 20327 | 726 | m_values(values) { | |
| 20328 | /* No op */ | ||
| 20329 | 726 | } | |
| 20330 | |||
| 20331 | /** Collect the latch metrics. Ignore entries where the | ||
| 20332 | spins and waits are zero. | ||
| 20333 | @param[in] count The latch metrics */ | ||
| 20334 | 19528 | void operator()(const Count *count) UNIV_NOTHROW { | |
| 20335 |
2/4✓ Branch 0 taken 19528 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19528 times.
|
19528 | if (count->m_spins > 0 || count->m_waits > 0) { |
| 20336 | ✗ | m_values->push_back( | |
| 20337 | ✗ | Value(m_name, count->m_spins, count->m_waits, count->m_calls)); | |
| 20338 | } | ||
| 20339 | 19528 | } | |
| 20340 | |||
| 20341 | /** The latch name */ | ||
| 20342 | const char *m_name; | ||
| 20343 | |||
| 20344 | /** For collecting the active mutex stats. */ | ||
| 20345 | Values *m_values; | ||
| 20346 | }; | ||
| 20347 | |||
| 20348 | /** Constructor */ | ||
| 20349 | 6 | ShowStatus() = default; | |
| 20350 | |||
| 20351 | /** Callback for collecting the stats | ||
| 20352 | @param[in] latch_meta Latch meta data | ||
| 20353 | @return always returns true */ | ||
| 20354 | 726 | bool operator()(latch_meta_t &latch_meta) UNIV_NOTHROW { | |
| 20355 |
1/2✓ Branch 0 taken 726 times.
✗ Branch 1 not taken.
|
1452 | latch_meta.get_counter()->iterate( |
| 20356 | 726 | GetCount{latch_meta.get_name(), &m_values}); | |
| 20357 | |||
| 20358 | 726 | return (true); | |
| 20359 | } | ||
| 20360 | |||
| 20361 | /** Implements the SHOW MUTEX STATUS command, for mutexes. | ||
| 20362 | The table structure is like so: Engine | Mutex Name | Status | ||
| 20363 | We store the metrics in the "Status" column as: | ||
| 20364 | |||
| 20365 | spins=N,waits=N,calls=N" | ||
| 20366 | |||
| 20367 | The user has to parse the data unfortunately | ||
| 20368 | @param[in,out] thd the MySQL query thread of the caller | ||
| 20369 | @param[in,out] stat_print function for printing statistics | ||
| 20370 | @return true on success. */ | ||
| 20371 | bool to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW; | ||
| 20372 | |||
| 20373 | /** For collecting the active mutex stats. */ | ||
| 20374 | Values m_values; | ||
| 20375 | }; | ||
| 20376 | |||
| 20377 | /** Implements the SHOW MUTEX STATUS command, for mutexes. | ||
| 20378 | The table structure is like so: Engine | Mutex Name | Status | ||
| 20379 | We store the metrics in the "Status" column as: | ||
| 20380 | |||
| 20381 | spins=N,waits=N,calls=N" | ||
| 20382 | |||
| 20383 | The user has to parse the data unfortunately | ||
| 20384 | @param[in,out] thd the MySQL query thread of the caller | ||
| 20385 | @param[in,out] stat_print function for printing statistics | ||
| 20386 | @return true on success. */ | ||
| 20387 | 6 | bool ShowStatus::to_string(THD *thd, stat_print_fn *stat_print) UNIV_NOTHROW { | |
| 20388 | 6 | uint hton_name_len = (uint)strlen(innobase_hton_name); | |
| 20389 | |||
| 20390 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | std::sort(m_values.begin(), m_values.end(), OrderByWaits()); |
| 20391 | |||
| 20392 | 6 | Values::iterator end = m_values.end(); | |
| 20393 | |||
| 20394 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | for (Values::iterator it = m_values.begin(); it != end; ++it) { |
| 20395 | int name_len; | ||
| 20396 | char name_buf[IO_SIZE]; | ||
| 20397 | |||
| 20398 | ✗ | name_len = snprintf(name_buf, sizeof(name_buf), "%s", it->m_name.c_str()); | |
| 20399 | |||
| 20400 | int status_len; | ||
| 20401 | char status_buf[IO_SIZE]; | ||
| 20402 | |||
| 20403 | ✗ | status_len = snprintf(status_buf, sizeof(status_buf), | |
| 20404 | "spins=%lu,waits=%lu,calls=" TRX_ID_FMT, | ||
| 20405 | ✗ | static_cast<ulong>(it->m_spins), | |
| 20406 | ✗ | static_cast<long>(it->m_waits), it->m_calls); | |
| 20407 | |||
| 20408 | ✗ | if (stat_print(thd, innobase_hton_name, hton_name_len, name_buf, | |
| 20409 | ✗ | static_cast<uint>(name_len), status_buf, | |
| 20410 | ✗ | static_cast<uint>(status_len))) { | |
| 20411 | ✗ | return (false); | |
| 20412 | } | ||
| 20413 | } | ||
| 20414 | |||
| 20415 | 6 | return (true); | |
| 20416 | } | ||
| 20417 | |||
| 20418 | /** Implements the SHOW MUTEX STATUS command, for mutexes. | ||
| 20419 | @param[in,out] hton the innodb handlerton | ||
| 20420 | @param[in,out] thd the MySQL query thread of the caller | ||
| 20421 | @param[in,out] stat_print function for printing statistics | ||
| 20422 | @return 0 on success. */ | ||
| 20423 | 6 | static int innodb_show_mutex_status(handlerton *hton, THD *thd, | |
| 20424 | stat_print_fn *stat_print) { | ||
| 20425 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_TRACE; |
| 20426 | |||
| 20427 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | ShowStatus collector; |
| 20428 | |||
| 20429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(hton == innodb_hton_ptr); |
| 20430 | |||
| 20431 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | mutex_monitor->iterate(collector); |
| 20432 | |||
| 20433 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (!collector.to_string(thd, stat_print)) { |
| 20434 | ✗ | return 1; | |
| 20435 | } | ||
| 20436 | |||
| 20437 | 6 | return 0; | |
| 20438 | 6 | } | |
| 20439 | |||
| 20440 | /** Implements the SHOW MUTEX STATUS command. | ||
| 20441 | @param[in,out] hton the innodb handlerton | ||
| 20442 | @param[in,out] thd the MySQL query thread of the caller | ||
| 20443 | @param[in,out] stat_print function for printing statistics | ||
| 20444 | @return 0 on success. */ | ||
| 20445 | 6 | static int innodb_show_rwlock_status(handlerton *hton, THD *thd, | |
| 20446 | stat_print_fn *stat_print) { | ||
| 20447 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | DBUG_TRACE; |
| 20448 | |||
| 20449 | 6 | rw_lock_t *block_rwlock = nullptr; | |
| 20450 | 6 | ulint block_rwlock_oswait_count = 0; | |
| 20451 | 6 | uint hton_name_len = (uint)strlen(innobase_hton_name); | |
| 20452 | |||
| 20453 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | assert(hton == innodb_hton_ptr); |
| 20454 | |||
| 20455 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | mutex_enter(&rw_lock_list_mutex); |
| 20456 | |||
| 20457 |
6/10✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20424 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20430 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20424 times.
✓ Branch 9 taken 6 times.
|
20430 | for (auto rw_lock : rw_lock_list) { |
| 20458 |
2/2✓ Branch 0 taken 20128 times.
✓ Branch 1 taken 296 times.
|
20424 | if (rw_lock->count_os_wait == 0) { |
| 20459 | 20337 | continue; | |
| 20460 | } | ||
| 20461 | |||
| 20462 | int buf1len; | ||
| 20463 | char buf1[IO_SIZE]; | ||
| 20464 | |||
| 20465 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 87 times.
|
296 | if (rw_lock->is_block_lock) { |
| 20466 | 209 | block_rwlock = rw_lock; | |
| 20467 | 209 | block_rwlock_oswait_count += rw_lock->count_os_wait; | |
| 20468 | |||
| 20469 | 209 | continue; | |
| 20470 | } | ||
| 20471 | |||
| 20472 | 174 | buf1len = snprintf(buf1, sizeof buf1, "rwlock: %s:%lu", | |
| 20473 | innobase_basename(rw_lock->clocation.filename), | ||
| 20474 |
1/2✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
|
87 | static_cast<ulong>(rw_lock->clocation.line)); |
| 20475 | |||
| 20476 | int buf2len; | ||
| 20477 | char buf2[IO_SIZE]; | ||
| 20478 | |||
| 20479 | 87 | buf2len = snprintf(buf2, sizeof buf2, "waits=%lu", | |
| 20480 | 87 | static_cast<ulong>(rw_lock->count_os_wait)); | |
| 20481 | |||
| 20482 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
|
87 | if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, |
| 20483 | 87 | static_cast<uint>(buf1len), buf2, | |
| 20484 |
1/2✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
|
87 | static_cast<uint>(buf2len))) { |
| 20485 | ✗ | mutex_exit(&rw_lock_list_mutex); | |
| 20486 | |||
| 20487 | ✗ | return 1; | |
| 20488 | } | ||
| 20489 | } | ||
| 20490 | |||
| 20491 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | if (block_rwlock != nullptr) { |
| 20492 | int buf1len; | ||
| 20493 | char buf1[IO_SIZE]; | ||
| 20494 | |||
| 20495 | 10 | buf1len = snprintf(buf1, sizeof buf1, "sum rwlock: %s:%lu", | |
| 20496 | innobase_basename(block_rwlock->clocation.filename), | ||
| 20497 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | static_cast<ulong>(block_rwlock->clocation.line)); |
| 20498 | |||
| 20499 | int buf2len; | ||
| 20500 | char buf2[IO_SIZE]; | ||
| 20501 | |||
| 20502 | 5 | buf2len = snprintf(buf2, sizeof buf2, "waits=%lu", | |
| 20503 | static_cast<ulong>(block_rwlock_oswait_count)); | ||
| 20504 | |||
| 20505 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, |
| 20506 | 5 | static_cast<uint>(buf1len), buf2, | |
| 20507 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | static_cast<uint>(buf2len))) { |
| 20508 | ✗ | mutex_exit(&rw_lock_list_mutex); | |
| 20509 | |||
| 20510 | ✗ | return 1; | |
| 20511 | } | ||
| 20512 | } | ||
| 20513 | |||
| 20514 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | mutex_exit(&rw_lock_list_mutex); |
| 20515 | |||
| 20516 | 6 | return 0; | |
| 20517 | 6 | } | |
| 20518 | |||
| 20519 | /** Implements the SHOW MUTEX STATUS command. | ||
| 20520 | @param[in,out] hton the innodb handlerton | ||
| 20521 | @param[in,out] thd the MySQL query thread of the caller | ||
| 20522 | @param[in,out] stat_print function for printing statistics | ||
| 20523 | @return 0 on success. */ | ||
| 20524 | 6 | static int innodb_show_latch_status(handlerton *hton, THD *thd, | |
| 20525 | stat_print_fn *stat_print) { | ||
| 20526 | 6 | int ret = innodb_show_mutex_status(hton, thd, stat_print); | |
| 20527 | |||
| 20528 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret != 0) { |
| 20529 | ✗ | return (ret); | |
| 20530 | } | ||
| 20531 | |||
| 20532 | 6 | return (innodb_show_rwlock_status(hton, thd, stat_print)); | |
| 20533 | } | ||
| 20534 | |||
| 20535 | /** Return 0 on success and non-zero on failure. Note: the bool return type | ||
| 20536 | seems to be abused here, should be an int. | ||
| 20537 | @param[in] hton the innodb handlerton | ||
| 20538 | @param[in] thd the MySQL query thread of the caller | ||
| 20539 | @param[in] stat_print print function | ||
| 20540 | @param[in] stat_type status to show */ | ||
| 20541 | 50 | static bool innobase_show_status(handlerton *hton, THD *thd, | |
| 20542 | stat_print_fn *stat_print, | ||
| 20543 | enum ha_stat_type stat_type) { | ||
| 20544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
|
50 | assert(hton == innodb_hton_ptr); |
| 20545 | |||
| 20546 |
3/4✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
50 | switch (stat_type) { |
| 20547 | 41 | case HA_ENGINE_STATUS: | |
| 20548 | /* Non-zero return value means there was an error. */ | ||
| 20549 | 41 | return (innodb_show_status(hton, thd, stat_print) != 0); | |
| 20550 | |||
| 20551 | 6 | case HA_ENGINE_MUTEX: | |
| 20552 | 6 | return (innodb_show_latch_status(hton, thd, stat_print) != 0); | |
| 20553 | |||
| 20554 | 3 | case HA_ENGINE_LOGS: | |
| 20555 | /* Not handled */ | ||
| 20556 | 3 | break; | |
| 20557 | } | ||
| 20558 | |||
| 20559 | /* Success */ | ||
| 20560 | 3 | return (false); | |
| 20561 | } | ||
| 20562 | |||
| 20563 | /** Handling the shared INNOBASE_SHARE structure that is needed to provide table | ||
| 20564 | locking. Register the table name if it doesn't exist in the hash table. */ | ||
| 20565 | 4556996 | static INNOBASE_SHARE *get_share(const char *table_name) { | |
| 20566 | INNOBASE_SHARE *share; | ||
| 20567 | |||
| 20568 | 4556996 | mysql_mutex_lock(&innobase_share_mutex); | |
| 20569 | |||
| 20570 | 4556997 | const auto hash_value = ut::hash_string(table_name); | |
| 20571 | |||
| 20572 |
5/6✗ Branch 0 not taken.
✓ Branch 1 taken 2799605 times.
✓ Branch 2 taken 2496752 times.
✓ Branch 3 taken 302853 times.
✓ Branch 4 taken 2799605 times.
✓ Branch 5 taken 2060245 times.
|
4859850 | HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value, |
| 20573 | INNOBASE_SHARE *, share, ut_ad(share->use_count > 0), | ||
| 20574 | !strcmp(share->table_name, table_name)); | ||
| 20575 | |||
| 20576 |
2/2✓ Branch 0 taken 2060245 times.
✓ Branch 1 taken 2496752 times.
|
4556997 | if (share == nullptr) { |
| 20577 | 2060245 | uint length = (uint)strlen(table_name); | |
| 20578 | |||
| 20579 | /* TODO: invoke HASH_MIGRATE if innobase_open_tables | ||
| 20580 | grows too big */ | ||
| 20581 | |||
| 20582 | share = reinterpret_cast<INNOBASE_SHARE *>( | ||
| 20583 | 2060245 | my_malloc(PSI_INSTRUMENT_ME, sizeof(*share) + length + 1, | |
| 20584 | MYF(MY_FAE | MY_ZEROFILL))); | ||
| 20585 | |||
| 20586 | 2060245 | share->table_name = | |
| 20587 | 2060245 | reinterpret_cast<char *>(memcpy(share + 1, table_name, length + 1)); | |
| 20588 | |||
| 20589 |
4/4✓ Branch 0 taken 1919077 times.
✓ Branch 1 taken 141168 times.
✓ Branch 2 taken 16575 times.
✓ Branch 3 taken 141168 times.
|
2076820 | HASH_INSERT(INNOBASE_SHARE, table_name_hash, innobase_open_tables, |
| 20590 | hash_value, share); | ||
| 20591 | |||
| 20592 | /* Index translation table initialization */ | ||
| 20593 | 2060245 | share->idx_trans_tbl.index_mapping = nullptr; | |
| 20594 | 2060245 | share->idx_trans_tbl.index_count = 0; | |
| 20595 | 2060245 | share->idx_trans_tbl.array_size = 0; | |
| 20596 | } | ||
| 20597 | |||
| 20598 | 4556997 | ++share->use_count; | |
| 20599 | |||
| 20600 | 4556997 | mysql_mutex_unlock(&innobase_share_mutex); | |
| 20601 | |||
| 20602 | 4556997 | return (share); | |
| 20603 | } | ||
| 20604 | |||
| 20605 | /** Free the shared object that was registered with get_share(). */ | ||
| 20606 | 4434067 | static void free_share( | |
| 20607 | INNOBASE_SHARE *share) /*!< in/own: table share to free */ | ||
| 20608 | { | ||
| 20609 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4434067 times.
|
4434067 | if (!share) { |
| 20610 | ✗ | return; | |
| 20611 | } | ||
| 20612 | |||
| 20613 | 4434067 | mysql_mutex_lock(&innobase_share_mutex); | |
| 20614 | |||
| 20615 | #ifdef UNIV_DEBUG | ||
| 20616 | INNOBASE_SHARE *share2; | ||
| 20617 | 4434068 | const auto hash_value = ut::hash_string(share->table_name); | |
| 20618 | |||
| 20619 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 4656529 times.
✓ Branch 2 taken 4434068 times.
✓ Branch 3 taken 222461 times.
✓ Branch 4 taken 4656529 times.
✗ Branch 5 not taken.
|
4656529 | HASH_SEARCH(table_name_hash, innobase_open_tables, hash_value, |
| 20620 | INNOBASE_SHARE *, share2, ut_ad(share->use_count > 0), | ||
| 20621 | !strcmp(share->table_name, share2->table_name)); | ||
| 20622 | |||
| 20623 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4434068 times.
|
4434068 | ut_a(share2 == share); |
| 20624 | #endif /* UNIV_DEBUG */ | ||
| 20625 | |||
| 20626 | 4434068 | --share->use_count; | |
| 20627 | |||
| 20628 |
2/2✓ Branch 0 taken 1994831 times.
✓ Branch 1 taken 2439237 times.
|
4434068 | if (share->use_count == 0) { |
| 20629 | 1994831 | const auto hash_value = ut::hash_string(share->table_name); | |
| 20630 | |||
| 20631 |
5/6✓ Branch 0 taken 1900321 times.
✓ Branch 1 taken 94510 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3690 times.
✓ Branch 4 taken 3690 times.
✓ Branch 5 taken 94510 times.
|
1998521 | HASH_DELETE(INNOBASE_SHARE, table_name_hash, innobase_open_tables, |
| 20632 | hash_value, share); | ||
| 20633 | |||
| 20634 | /* Free any memory from index translation table */ | ||
| 20635 | 1994831 | ut::free(share->idx_trans_tbl.index_mapping); | |
| 20636 | |||
| 20637 | 1994831 | my_free(share); | |
| 20638 | |||
| 20639 | /* TODO: invoke HASH_MIGRATE if innobase_open_tables | ||
| 20640 | shrinks too much */ | ||
| 20641 | } | ||
| 20642 | |||
| 20643 | 4434068 | mysql_mutex_unlock(&innobase_share_mutex); | |
| 20644 | } | ||
| 20645 | |||
| 20646 | /** Returns number of THR_LOCK locks used for one instance of InnoDB table. | ||
| 20647 | InnoDB no longer relies on THR_LOCK locks so 0 value is returned. | ||
| 20648 | Instead of THR_LOCK locks InnoDB relies on combination of metadata locks | ||
| 20649 | (e.g. for LOCK TABLES and DDL) and its own locking subsystem. | ||
| 20650 | Note that even though this method returns 0, SQL-layer still calls | ||
| 20651 | "::store_lock()", "::start_stmt()" and "::external_lock()" methods for InnoDB | ||
| 20652 | tables. */ | ||
| 20653 | |||
| 20654 | 112013471 | uint ha_innobase::lock_count(void) const { return 0; } | |
| 20655 | |||
| 20656 | /** Supposed to convert a MySQL table lock stored in the 'lock' field of the | ||
| 20657 | handle to a proper type before storing pointer to the lock into an array | ||
| 20658 | of pointers. | ||
| 20659 | In practice, since InnoDB no longer relies on THR_LOCK locks and its | ||
| 20660 | lock_count() method returns 0 it just informs storage engine about type | ||
| 20661 | of THR_LOCK which SQL-layer would have acquired for this specific statement | ||
| 20662 | on this specific table. | ||
| 20663 | MySQL also calls this if it wants to reset some table locks to a not-locked | ||
| 20664 | state during the processing of an SQL query. An example is that during a | ||
| 20665 | SELECT the read lock is released early on the 'const' tables where we only | ||
| 20666 | fetch one row. MySQL does not call this when it releases all locks at the | ||
| 20667 | end of an SQL statement. | ||
| 20668 | @return pointer to the current element in the 'to' array. */ | ||
| 20669 | |||
| 20670 | 112013862 | THR_LOCK_DATA **ha_innobase::store_lock( | |
| 20671 | THD *thd, /*!< in: user thread handle */ | ||
| 20672 | THR_LOCK_DATA **to, /*!< in: pointer to the current | ||
| 20673 | element in an array of pointers | ||
| 20674 | to lock structs; | ||
| 20675 | only used as return value */ | ||
| 20676 | thr_lock_type lock_type) /*!< in: lock type to store in | ||
| 20677 | 'lock'; this may also be | ||
| 20678 | TL_IGNORE */ | ||
| 20679 | { | ||
| 20680 | /* Note that trx in this function is NOT necessarily m_prebuilt->trx | ||
| 20681 | because we call update_thd() later, in ::external_lock()! Failure to | ||
| 20682 | understand this caused a serious memory corruption bug in 5.1.11. */ | ||
| 20683 | |||
| 20684 |
1/2✓ Branch 0 taken 112014783 times.
✗ Branch 1 not taken.
|
112013862 | trx_t *trx = check_trx_exists(thd); |
| 20685 | |||
| 20686 |
1/2✓ Branch 0 taken 112014231 times.
✗ Branch 1 not taken.
|
112014783 | TrxInInnoDB trx_in_innodb(trx); |
| 20687 | |||
| 20688 | /* NOTE: MySQL can call this function with lock 'type' TL_IGNORE! | ||
| 20689 | Be careful to ignore TL_IGNORE if we are going to do something with | ||
| 20690 | only 'real' locks! */ | ||
| 20691 | |||
| 20692 | /* If no MySQL table is in use, we need to set the isolation level | ||
| 20693 | of the transaction. */ | ||
| 20694 | |||
| 20695 |
4/4✓ Branch 0 taken 111918847 times.
✓ Branch 1 taken 95384 times.
✓ Branch 2 taken 111542011 times.
✓ Branch 3 taken 376836 times.
|
112014231 | if (lock_type != TL_IGNORE && trx->n_mysql_tables_in_use == 0) { |
| 20696 | 111541634 | trx->isolation_level = | |
| 20697 |
2/4✓ Branch 0 taken 111541665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111541634 times.
✗ Branch 3 not taken.
|
111542011 | innobase_trx_map_isolation_level(thd_get_trx_isolation(thd)); |
| 20698 | |||
| 20699 |
4/4✓ Branch 0 taken 78740215 times.
✓ Branch 1 taken 32801419 times.
✓ Branch 2 taken 198 times.
✓ Branch 3 taken 111541392 times.
|
190281805 | if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && |
| 20700 |
3/4✓ Branch 0 taken 78740171 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 198 times.
✓ Branch 3 taken 78739973 times.
|
78740215 | MVCC::is_view_active(trx->read_view)) { |
| 20701 | /* At low transaction isolation levels we let | ||
| 20702 | each consistent read set its own snapshot */ | ||
| 20703 | |||
| 20704 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | mutex_enter(&trx_sys->mutex); |
| 20705 | |||
| 20706 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | trx_sys->mvcc->view_close(trx->read_view, true); |
| 20707 | |||
| 20708 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | mutex_exit(&trx_sys->mutex); |
| 20709 | } | ||
| 20710 | } | ||
| 20711 | |||
| 20712 |
2/4✓ Branch 0 taken 112013756 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 112013756 times.
|
112013810 | assert(EQ_CURRENT_THD(thd)); |
| 20713 |
1/2✓ Branch 0 taken 112013858 times.
✗ Branch 1 not taken.
|
112013756 | const bool in_lock_tables = thd_in_lock_tables(thd); |
| 20714 |
1/2✓ Branch 0 taken 112014064 times.
✗ Branch 1 not taken.
|
112013858 | const uint sql_command = thd_sql_command(thd); |
| 20715 | |||
| 20716 |
8/10✓ Branch 0 taken 75589 times.
✓ Branch 1 taken 111938475 times.
✓ Branch 2 taken 75589 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 75589 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 75279 times.
✓ Branch 7 taken 310 times.
✓ Branch 8 taken 940 times.
✓ Branch 9 taken 112013124 times.
|
112089343 | if (srv_read_only_mode && !m_prebuilt->table->is_intrinsic() && |
| 20717 |
4/4✓ Branch 0 taken 74960 times.
✓ Branch 1 taken 319 times.
✓ Branch 2 taken 74959 times.
✓ Branch 3 taken 1 times.
|
75279 | (sql_command == SQLCOM_UPDATE || sql_command == SQLCOM_INSERT || |
| 20718 |
2/4✓ Branch 0 taken 74959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74959 times.
✗ Branch 3 not taken.
|
74959 | sql_command == SQLCOM_REPLACE || sql_command == SQLCOM_DROP_TABLE || |
| 20719 |
2/4✓ Branch 0 taken 74959 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74959 times.
|
74959 | sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || |
| 20720 | ✗ | (sql_command == SQLCOM_CREATE_TABLE && | |
| 20721 |
1/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 74959 times.
✗ Branch 3 not taken.
|
74959 | (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE)) || |
| 20722 |
3/4✓ Branch 0 taken 74959 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74656 times.
✓ Branch 3 taken 303 times.
|
74959 | sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX || |
| 20723 |
2/2✓ Branch 0 taken 74653 times.
✓ Branch 1 taken 3 times.
|
74656 | sql_command == SQLCOM_DELETE || |
| 20724 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 74649 times.
|
74653 | sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY || |
| 20725 | sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) { | ||
| 20726 |
1/2✓ Branch 0 taken 940 times.
✗ Branch 1 not taken.
|
940 | ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); |
| 20727 | |||
| 20728 |
4/4✓ Branch 0 taken 129665 times.
✓ Branch 1 taken 111883459 times.
✓ Branch 2 taken 464 times.
✓ Branch 3 taken 129201 times.
|
112013124 | } else if (sql_command == SQLCOM_FLUSH && lock_type == TL_READ_NO_INSERT) { |
| 20729 | /* Check for FLUSH TABLES ... WITH READ LOCK */ | ||
| 20730 | |||
| 20731 | /* Note: This call can fail, but there is no way to return | ||
| 20732 | the error to the caller. We simply ignore it for now here | ||
| 20733 | and push the error code to the caller where the error is | ||
| 20734 | detected in the function. */ | ||
| 20735 | |||
| 20736 |
1/2✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
|
464 | dberr_t err = row_quiesce_set_state(m_prebuilt->table, QUIESCE_START, trx); |
| 20737 | |||
| 20738 |
4/6✓ Branch 0 taken 8 times.
✓ Branch 1 taken 456 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 464 times.
|
464 | ut_a(err == DB_SUCCESS || err == DB_UNSUPPORTED); |
| 20739 | |||
| 20740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
|
464 | if (trx->isolation_level == TRX_ISO_SERIALIZABLE) { |
| 20741 | ✗ | m_prebuilt->select_lock_type = LOCK_S; | |
| 20742 | ✗ | m_stored_select_lock_type = LOCK_S; | |
| 20743 | } else { | ||
| 20744 | 464 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 20745 | 464 | m_stored_select_lock_type = LOCK_NONE; | |
| 20746 | } | ||
| 20747 | |||
| 20748 | /* Check for DROP TABLE */ | ||
| 20749 |
2/2✓ Branch 0 taken 112011950 times.
✓ Branch 1 taken 710 times.
|
112013124 | } else if (sql_command == SQLCOM_DROP_TABLE) { |
| 20750 | /* MySQL calls this function in DROP TABLE though this table | ||
| 20751 | handle may belong to another thd that is running a query. Let | ||
| 20752 | us in that case skip any changes to the m_prebuilt struct. */ | ||
| 20753 | |||
| 20754 | /* Check for LOCK TABLE t1,...,tn WITH SHARED LOCKS */ | ||
| 20755 |
6/6✓ Branch 0 taken 82619359 times.
✓ Branch 1 taken 29392591 times.
✓ Branch 2 taken 82617954 times.
✓ Branch 3 taken 1405 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 112010525 times.
|
112011950 | } else if ((lock_type == TL_READ && in_lock_tables) || |
| 20756 |
3/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112010371 times.
✓ Branch 3 taken 174 times.
|
112010545 | (lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables) || |
| 20757 |
2/2✓ Branch 0 taken 111918728 times.
✓ Branch 1 taken 91643 times.
|
112010371 | lock_type == TL_READ_WITH_SHARED_LOCKS || |
| 20758 |
2/2✓ Branch 0 taken 111823515 times.
✓ Branch 1 taken 95213 times.
|
111918728 | lock_type == TL_READ_NO_INSERT || |
| 20759 |
2/2✓ Branch 0 taken 31267057 times.
✓ Branch 1 taken 80556458 times.
|
111823515 | (lock_type != TL_IGNORE && sql_command != SQLCOM_SELECT)) { |
| 20760 | /* The OR cases above are in this order: | ||
| 20761 | 1) MySQL is doing LOCK TABLES ... READ LOCAL, or we | ||
| 20762 | are processing a stored procedure or function, or | ||
| 20763 | 2) (we do not know when TL_READ_HIGH_PRIORITY is used), or | ||
| 20764 | 3) this is a SELECT ... IN SHARE MODE/FOR SHARE, or | ||
| 20765 | 4) we are doing a complex SQL statement like | ||
| 20766 | INSERT INTO ... SELECT ... and the logical logging (MySQL | ||
| 20767 | binlog) requires the use of a locking read, or | ||
| 20768 | MySQL is doing LOCK TABLES ... READ. | ||
| 20769 | 5) we let InnoDB do locking reads for all SQL statements that | ||
| 20770 | are not simple SELECTs; note that select_lock_type in this | ||
| 20771 | case may get strengthened in ::external_lock() to LOCK_X. | ||
| 20772 | Note that we MUST use a locking read in all data modifying | ||
| 20773 | SQL statements, because otherwise the execution would not be | ||
| 20774 | serializable, and also the results from the update could be | ||
| 20775 | unexpected if an obsolete consistent read view would be | ||
| 20776 | used. */ | ||
| 20777 | |||
| 20778 | /* Use consistent read for checksum table */ | ||
| 20779 | |||
| 20780 |
4/4✓ Branch 0 taken 30693666 times.
✓ Branch 1 taken 666613 times.
✓ Branch 2 taken 667071 times.
✓ Branch 3 taken 30693177 times.
|
62053914 | if (sql_command == SQLCOM_CHECKSUM || |
| 20781 |
5/6✓ Branch 0 taken 30693635 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 478067 times.
✓ Branch 3 taken 30215568 times.
✓ Branch 4 taken 471476 times.
✓ Branch 5 taken 6591 times.
|
30693666 | (trx->skip_gap_locks() && |
| 20782 |
4/4✓ Branch 0 taken 373 times.
✓ Branch 1 taken 471103 times.
✓ Branch 2 taken 6639 times.
✓ Branch 3 taken 325 times.
|
478067 | (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) && |
| 20783 |
2/2✓ Branch 0 taken 6635 times.
✓ Branch 1 taken 4 times.
|
6639 | (sql_command == SQLCOM_INSERT_SELECT || |
| 20784 |
2/2✓ Branch 0 taken 6574 times.
✓ Branch 1 taken 61 times.
|
6635 | sql_command == SQLCOM_REPLACE_SELECT || |
| 20785 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 6522 times.
|
6574 | sql_command == SQLCOM_UPDATE || |
| 20786 | sql_command == SQLCOM_CREATE_TABLE))) { | ||
| 20787 | /* If this session is using READ COMMITTED or READ | ||
| 20788 | UNCOMMITTED isolation level and MySQL is doing INSERT | ||
| 20789 | INTO... SELECT or REPLACE INTO...SELECT or UPDATE ... | ||
| 20790 | = (SELECT ...) or CREATE ... SELECT... without FOR | ||
| 20791 | UPDATE or IN SHARE MODE in select, then we use | ||
| 20792 | consistent read for select. | ||
| 20793 | |||
| 20794 | See also similar code in ha_innobase::start_stmt(). */ | ||
| 20795 | |||
| 20796 | 667071 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 20797 | 667071 | m_stored_select_lock_type = LOCK_NONE; | |
| 20798 | } else { | ||
| 20799 | 30693177 | m_prebuilt->select_lock_type = LOCK_S; | |
| 20800 | 30693177 | m_stored_select_lock_type = LOCK_S; | |
| 20801 | } | ||
| 20802 | |||
| 20803 |
2/2✓ Branch 0 taken 80557087 times.
✓ Branch 1 taken 94584 times.
|
80651671 | } else if (lock_type != TL_IGNORE) { |
| 20804 | /* We set possible LOCK_X value in external_lock, not yet | ||
| 20805 | here even if this would be SELECT ... FOR UPDATE */ | ||
| 20806 | |||
| 20807 | 80557087 | m_prebuilt->select_lock_type = LOCK_NONE; | |
| 20808 | 80557087 | m_stored_select_lock_type = LOCK_NONE; | |
| 20809 | } | ||
| 20810 | |||
| 20811 | /* Set select mode for SKIP LOCKED / NOWAIT */ | ||
| 20812 |
2/2✓ Branch 0 taken 111918527 times.
✓ Branch 1 taken 95506 times.
|
112014033 | if (lock_type != TL_IGNORE) { |
| 20813 |
3/3✓ Branch 0 taken 100 times.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 111918555 times.
|
111918527 | switch (table->pos_in_table_list->lock_descriptor().action) { |
| 20814 | 100 | case THR_SKIP: | |
| 20815 | 100 | m_prebuilt->select_mode = SELECT_SKIP_LOCKED; | |
| 20816 | 100 | break; | |
| 20817 | 96 | case THR_NOWAIT: | |
| 20818 | 96 | m_prebuilt->select_mode = SELECT_NOWAIT; | |
| 20819 | 96 | break; | |
| 20820 | 111918555 | default: | |
| 20821 | 111918555 | m_prebuilt->select_mode = SELECT_ORDINARY; | |
| 20822 | 111918555 | break; | |
| 20823 | } | ||
| 20824 | } | ||
| 20825 | |||
| 20826 | /* Ignore SKIP LOCKED / NO_WAIT for high priority transaction */ | ||
| 20827 |
3/4✓ Branch 0 taken 112013573 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 213088 times.
✓ Branch 3 taken 111800485 times.
|
112014257 | if (trx_is_high_priority(trx)) { |
| 20828 | 213088 | m_prebuilt->select_mode = SELECT_ORDINARY; | |
| 20829 | } | ||
| 20830 | |||
| 20831 |
7/8✓ Branch 0 taken 112014114 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91125924 times.
✓ Branch 3 taken 20888190 times.
✓ Branch 4 taken 81218172 times.
✓ Branch 5 taken 9907752 times.
✓ Branch 6 taken 9907801 times.
✓ Branch 7 taken 102106313 times.
|
193231745 | if (!trx_is_started(trx) && (m_prebuilt->select_lock_type != LOCK_NONE || |
| 20832 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 81218132 times.
|
81218172 | m_stored_select_lock_type != LOCK_NONE)) { |
| 20833 | 9907801 | ++trx->will_lock; | |
| 20834 | } | ||
| 20835 | |||
| 20836 | #ifdef UNIV_DEBUG | ||
| 20837 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112014114 times.
|
112014114 | if (trx->is_dd_trx) { |
| 20838 | ✗ | ut_ad(trx->will_lock == 0 && m_prebuilt->select_lock_type == LOCK_NONE); | |
| 20839 | } | ||
| 20840 | #endif /* UNIV_DEBUG */ | ||
| 20841 | |||
| 20842 | 112014639 | return (to); | |
| 20843 | 112014114 | } | |
| 20844 | |||
| 20845 | /** Read the next autoinc value. Acquire the relevant locks before reading | ||
| 20846 | the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked | ||
| 20847 | on return and all relevant locks acquired. | ||
| 20848 | @return DB_SUCCESS or error code */ | ||
| 20849 | |||
| 20850 | 8033551 | dberr_t ha_innobase::innobase_get_autoinc( | |
| 20851 | ulonglong *value) /*!< out: autoinc value */ | ||
| 20852 | { | ||
| 20853 | 8033551 | *value = 0; | |
| 20854 | |||
| 20855 | 8033551 | m_prebuilt->autoinc_error = innobase_lock_autoinc(); | |
| 20856 | |||
| 20857 |
1/2✓ Branch 0 taken 8033608 times.
✗ Branch 1 not taken.
|
8033594 | if (m_prebuilt->autoinc_error == DB_SUCCESS) { |
| 20858 | /* Determine the first value of the interval */ | ||
| 20859 | 8033608 | *value = dict_table_autoinc_read(m_prebuilt->table); | |
| 20860 | |||
| 20861 | /* It should have been initialized during open. */ | ||
| 20862 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8033613 times.
|
8033613 | if (*value == 0) { |
| 20863 | ✗ | m_prebuilt->autoinc_error = DB_UNSUPPORTED; | |
| 20864 | ✗ | dict_table_autoinc_unlock(m_prebuilt->table); | |
| 20865 | } | ||
| 20866 | } | ||
| 20867 | |||
| 20868 | 8033620 | return (m_prebuilt->autoinc_error); | |
| 20869 | } | ||
| 20870 | |||
| 20871 | 20936658 | void ha_innobase::release_auto_increment() { | |
| 20872 | 20936658 | trx_t *trx = m_prebuilt->trx; | |
| 20873 |
1/2✓ Branch 0 taken 20936670 times.
✗ Branch 1 not taken.
|
20936658 | TrxInInnoDB trx_in_innodb(trx); |
| 20874 | |||
| 20875 | /* Clear the trx's autoinc_rows as the operation requiring auto increment | ||
| 20876 | values has been completed. | ||
| 20877 | |||
| 20878 | We usually end up in this scenario when we do not know the correct estimation | ||
| 20879 | of rows in the table in the case of bulk inserts. */ | ||
| 20880 |
2/2✓ Branch 0 taken 7424 times.
✓ Branch 1 taken 20929246 times.
|
20936670 | if (trx->n_autoinc_rows > 0) { |
| 20881 | 7424 | trx->n_autoinc_rows = 0; | |
| 20882 | } | ||
| 20883 | 20936670 | } | |
| 20884 | |||
| 20885 | /** Returns the value of the auto-inc counter in *first_value and ~0 on failure. | ||
| 20886 | */ | ||
| 20887 | |||
| 20888 | 8033472 | void ha_innobase::get_auto_increment( | |
| 20889 | ulonglong offset, /*!< in: table autoinc offset */ | ||
| 20890 | ulonglong increment, /*!< in: table autoinc | ||
| 20891 | increment */ | ||
| 20892 | ulonglong nb_desired_values, /*!< in: number of values | ||
| 20893 | reqd */ | ||
| 20894 | ulonglong *first_value, /*!< out: the autoinc value */ | ||
| 20895 | ulonglong *nb_reserved_values) /*!< out: count of reserved | ||
| 20896 | values */ | ||
| 20897 | { | ||
| 20898 | trx_t *trx; | ||
| 20899 | dberr_t error; | ||
| 20900 | 8033472 | ulonglong autoinc = 0; | |
| 20901 | |||
| 20902 | /* Prepare m_prebuilt->trx in the table handle */ | ||
| 20903 |
2/4✓ Branch 0 taken 8033648 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8033666 times.
✗ Branch 3 not taken.
|
8033472 | update_thd(ha_thd()); |
| 20904 | |||
| 20905 |
1/2✓ Branch 0 taken 8033622 times.
✗ Branch 1 not taken.
|
8033666 | error = innobase_get_autoinc(&autoinc); |
| 20906 | |||
| 20907 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8033621 times.
|
8033622 | if (error != DB_SUCCESS) { |
| 20908 | 1 | *first_value = (~(ulonglong)0); | |
| 20909 | 1 | return; | |
| 20910 | } | ||
| 20911 | |||
| 20912 | /* This is a hack, since nb_desired_values seems to be accurate only | ||
| 20913 | for the first call to get_auto_increment() for multi-row INSERT and | ||
| 20914 | meaningless for other statements e.g, LOAD etc. Subsequent calls to | ||
| 20915 | this method for the same statement results in different values which | ||
| 20916 | don't make sense. Therefore we store the value the first time we are | ||
| 20917 | called and count down from that as rows are written (see write_row()). | ||
| 20918 | */ | ||
| 20919 | |||
| 20920 | 8033621 | trx = m_prebuilt->trx; | |
| 20921 | |||
| 20922 |
1/2✓ Branch 0 taken 8033642 times.
✗ Branch 1 not taken.
|
8033621 | TrxInInnoDB trx_in_innodb(trx); |
| 20923 | |||
| 20924 | /* Note: We can't rely on *first_value since some MySQL engines, | ||
| 20925 | in particular the partition engine, don't initialize it to 0 when | ||
| 20926 | invoking this method. So we are not sure if it's guaranteed to | ||
| 20927 | be 0 or not. */ | ||
| 20928 | |||
| 20929 | /* We need the upper limit of the col type to check for | ||
| 20930 | whether we update the table autoinc counter or not. */ | ||
| 20931 |
1/2✓ Branch 0 taken 8033658 times.
✗ Branch 1 not taken.
|
8033642 | ulonglong col_max_value = table->next_number_field->get_max_int_value(); |
| 20932 | |||
| 20933 | /** The following logic is needed to avoid duplicate key error | ||
| 20934 | for autoincrement column. | ||
| 20935 | |||
| 20936 | (1) InnoDB gives the current autoincrement value with respect | ||
| 20937 | to increment and offset value. | ||
| 20938 | |||
| 20939 | (2) Basically it does compute_next_insert_id() logic inside InnoDB | ||
| 20940 | to avoid the current auto increment value changed by handler layer. | ||
| 20941 | |||
| 20942 | (3) It is restricted only for insert operations. */ | ||
| 20943 | |||
| 20944 |
4/4✓ Branch 0 taken 5808 times.
✓ Branch 1 taken 8027850 times.
✓ Branch 2 taken 5806 times.
✓ Branch 3 taken 2 times.
|
8033658 | if (increment > 1 && m_prebuilt->table->skip_alter_undo == false && |
| 20945 |
2/2✓ Branch 0 taken 5798 times.
✓ Branch 1 taken 8 times.
|
5806 | autoinc < col_max_value) { |
| 20946 | 5798 | ulonglong diff = ULLONG_MAX - autoinc; | |
| 20947 | /* Check for overflow */ | ||
| 20948 |
2/2✓ Branch 0 taken 5796 times.
✓ Branch 1 taken 2 times.
|
5798 | if (increment <= diff) { |
| 20949 | 5796 | ulonglong prev_auto_inc = autoinc; | |
| 20950 | 5796 | autoinc = ((autoinc - 1) + increment - offset) / increment; | |
| 20951 | 5796 | autoinc = autoinc * increment + offset; | |
| 20952 | |||
| 20953 | /* If autoinc exceeds the col_max_value then reset | ||
| 20954 | to old autoinc value. Because in case of non-strict | ||
| 20955 | sql mode, boundary value is not considered as error. */ | ||
| 20956 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5796 times.
|
5796 | if (autoinc >= col_max_value) { |
| 20957 | ✗ | autoinc = prev_auto_inc; | |
| 20958 | } | ||
| 20959 | |||
| 20960 |
2/2✓ Branch 0 taken 97 times.
✓ Branch 1 taken 5699 times.
|
5796 | ut_ad(autoinc > 0); |
| 20961 | } | ||
| 20962 | } | ||
| 20963 | |||
| 20964 | /* Called for the first time ? */ | ||
| 20965 |
2/2✓ Branch 0 taken 8033487 times.
✓ Branch 1 taken 74 times.
|
8033561 | if (trx->n_autoinc_rows == 0) { |
| 20966 | 8033487 | trx->n_autoinc_rows = (ulint)nb_desired_values; | |
| 20967 | |||
| 20968 | /* It's possible for nb_desired_values to be 0: | ||
| 20969 | e.g., INSERT INTO T1(C) SELECT C FROM T2; */ | ||
| 20970 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8033487 times.
|
8033487 | if (nb_desired_values == 0) { |
| 20971 | ✗ | trx->n_autoinc_rows = 1; | |
| 20972 | } | ||
| 20973 | |||
| 20974 | 8033487 | *first_value = std::max(*first_value, autoinc); | |
| 20975 | /* Not in the middle of a mult-row INSERT. */ | ||
| 20976 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 56 times.
|
74 | } else if (m_prebuilt->autoinc_last_value == 0) { |
| 20977 | 18 | *first_value = std::max(*first_value, autoinc); | |
| 20978 | /* Check for -ve values. */ | ||
| 20979 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
56 | } else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) { |
| 20980 | /* Set to next logical value. */ | ||
| 20981 | ✗ | ut_a(autoinc > trx->n_autoinc_rows); | |
| 20982 | ✗ | *first_value = (autoinc - trx->n_autoinc_rows) - 1; | |
| 20983 | } | ||
| 20984 | |||
| 20985 | 8033553 | *nb_reserved_values = trx->n_autoinc_rows; | |
| 20986 | |||
| 20987 | /* With old style AUTOINC locking we only update the table's | ||
| 20988 | AUTOINC counter after attempting to insert the row. */ | ||
| 20989 |
2/2✓ Branch 0 taken 10959 times.
✓ Branch 1 taken 8022594 times.
|
8033553 | if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING || |
| 20990 |
2/2✓ Branch 0 taken 8041 times.
✓ Branch 1 taken 2918 times.
|
10959 | m_prebuilt->no_autoinc_locking) { |
| 20991 | ulonglong current; | ||
| 20992 | ulonglong next_value; | ||
| 20993 | |||
| 20994 |
2/2✓ Branch 0 taken 8030593 times.
✓ Branch 1 taken 42 times.
|
8030635 | current = *first_value > col_max_value ? autoinc : *first_value; |
| 20995 | |||
| 20996 | /* Compute the last value in the interval */ | ||
| 20997 |
1/2✓ Branch 0 taken 8030737 times.
✗ Branch 1 not taken.
|
8030635 | next_value = innobase_next_autoinc(current, *nb_reserved_values, increment, |
| 20998 | offset, col_max_value); | ||
| 20999 | |||
| 21000 | 8030737 | m_prebuilt->autoinc_last_value = next_value; | |
| 21001 | |||
| 21002 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8030736 times.
|
8030737 | if (m_prebuilt->autoinc_last_value < *first_value) { |
| 21003 | 1 | *first_value = (~(ulonglong)0); | |
| 21004 | } else { | ||
| 21005 | /* Update the table autoinc variable */ | ||
| 21006 | 8030736 | dict_table_autoinc_update_if_greater(m_prebuilt->table, | |
| 21007 |
1/2✓ Branch 0 taken 8030714 times.
✗ Branch 1 not taken.
|
8030736 | m_prebuilt->autoinc_last_value); |
| 21008 | } | ||
| 21009 | 8030715 | } else { | |
| 21010 | /* This will force write_row() into attempting an update | ||
| 21011 | of the table's AUTOINC counter. */ | ||
| 21012 | 2918 | m_prebuilt->autoinc_last_value = 0; | |
| 21013 | } | ||
| 21014 | |||
| 21015 | /* The increment to be used to increase the AUTOINC value, we use | ||
| 21016 | this in write_row() and update_row() to increase the autoinc counter | ||
| 21017 | for columns that are filled by the user. We need the offset and | ||
| 21018 | the increment. */ | ||
| 21019 | 8033633 | m_prebuilt->autoinc_offset = offset; | |
| 21020 | 8033633 | m_prebuilt->autoinc_increment = increment; | |
| 21021 | |||
| 21022 |
1/2✓ Branch 0 taken 8033623 times.
✗ Branch 1 not taken.
|
8033633 | dict_table_autoinc_unlock(m_prebuilt->table); |
| 21023 | 8033623 | } | |
| 21024 | |||
| 21025 | /** See comment in handler.cc */ | ||
| 21026 | |||
| 21027 | 557 | bool ha_innobase::get_error_message(int error, String *buf) { | |
| 21028 | 557 | trx_t *trx = check_trx_exists(ha_thd()); | |
| 21029 | |||
| 21030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 557 times.
|
557 | if (error == HA_ERR_ENCRYPTION_KEY_MISSING) { |
| 21031 | ✗ | const char *msg = | |
| 21032 | "Table encrypted but decryption key was not found. " | ||
| 21033 | "Is correct keyring loaded?"; | ||
| 21034 | ✗ | buf->copy(msg, (uint)strlen(msg), system_charset_info); | |
| 21035 | } else { | ||
| 21036 | 557 | buf->copy(trx->detailed_error, (uint)strlen(trx->detailed_error), | |
| 21037 | system_charset_info); | ||
| 21038 | } | ||
| 21039 | |||
| 21040 | 557 | return false; | |
| 21041 | } | ||
| 21042 | |||
| 21043 | /** Retrieves the names of the table and the key for which there was a | ||
| 21044 | duplicate entry in the case of HA_ERR_FOREIGN_DUPLICATE_KEY. | ||
| 21045 | |||
| 21046 | If any of the names is not available, then this method will return | ||
| 21047 | false and will not change any of child_table_name or child_key_name. | ||
| 21048 | |||
| 21049 | @param[out] child_table_name Table name | ||
| 21050 | @param[in] child_table_name_len Table name buffer size | ||
| 21051 | @param[out] child_key_name Key name | ||
| 21052 | @param[in] child_key_name_len Key name buffer size | ||
| 21053 | |||
| 21054 | @retval true table and key names were available and were written into the | ||
| 21055 | corresponding out parameters. | ||
| 21056 | @retval false table and key names were not available, the out parameters | ||
| 21057 | were not touched. */ | ||
| 21058 | 3 | bool ha_innobase::get_foreign_dup_key(char *child_table_name, | |
| 21059 | uint child_table_name_len, | ||
| 21060 | char *child_key_name, | ||
| 21061 | uint child_key_name_len) { | ||
| 21062 | const dict_index_t *err_index; | ||
| 21063 | |||
| 21064 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | ut_a(m_prebuilt->trx != nullptr); |
| 21065 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N); |
| 21066 | |||
| 21067 | 3 | err_index = trx_get_error_index(m_prebuilt->trx); | |
| 21068 | |||
| 21069 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (err_index == nullptr) { |
| 21070 | ✗ | return (false); | |
| 21071 | } | ||
| 21072 | /* else */ | ||
| 21073 | |||
| 21074 | /* copy table name (and convert from filename-safe encoding to | ||
| 21075 | system_charset_info) */ | ||
| 21076 | 3 | char *p = strchr(err_index->table->name.m_name, '/'); | |
| 21077 | |||
| 21078 | /* strip ".../" prefix if any */ | ||
| 21079 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (p != nullptr) { |
| 21080 | 3 | p++; | |
| 21081 | } else { | ||
| 21082 | ✗ | p = err_index->table->name.m_name; | |
| 21083 | } | ||
| 21084 | |||
| 21085 | size_t len; | ||
| 21086 | |||
| 21087 | 3 | len = filename_to_tablename(p, child_table_name, child_table_name_len); | |
| 21088 | |||
| 21089 | 3 | child_table_name[len] = '\0'; | |
| 21090 | |||
| 21091 | /* copy index name */ | ||
| 21092 | 3 | snprintf(child_key_name, child_key_name_len, "%s", err_index->name()); | |
| 21093 | |||
| 21094 | 3 | return (true); | |
| 21095 | } | ||
| 21096 | |||
| 21097 | /** Compares two 'refs'. A 'ref' is the (internal) primary key value of the row. | ||
| 21098 | If there is no explicitly declared non-null unique key or a primary key, then | ||
| 21099 | InnoDB internally uses the row id as the primary key. | ||
| 21100 | @return < 0 if ref1 < ref2, 0 if equal, else > 0 */ | ||
| 21101 | |||
| 21102 | 2374704 | int ha_innobase::cmp_ref( | |
| 21103 | const uchar *ref1, /*!< in: an (internal) primary key value in the | ||
| 21104 | MySQL key value format */ | ||
| 21105 | const uchar *ref2) /*!< in: an (internal) primary key value in the | ||
| 21106 | MySQL key value format */ | ||
| 21107 | const { | ||
| 21108 | enum_field_types mysql_type; | ||
| 21109 | Field *field; | ||
| 21110 | KEY_PART_INFO *key_part; | ||
| 21111 | KEY_PART_INFO *key_part_end; | ||
| 21112 | uint len1; | ||
| 21113 | uint len2; | ||
| 21114 | int result; | ||
| 21115 | |||
| 21116 |
2/2✓ Branch 0 taken 1507624 times.
✓ Branch 1 taken 867080 times.
|
2374704 | if (m_prebuilt->clust_index_was_generated) { |
| 21117 | /* The 'ref' is an InnoDB row id */ | ||
| 21118 | |||
| 21119 | 1507624 | return (memcmp(ref1, ref2, DATA_ROW_ID_LEN)); | |
| 21120 | } | ||
| 21121 | |||
| 21122 | /* Do a type-aware comparison of primary key fields. PK fields | ||
| 21123 | are always NOT NULL, so no checks for NULL are performed. */ | ||
| 21124 | |||
| 21125 | 867080 | key_part = table->key_info[table->s->primary_key].key_part; | |
| 21126 | |||
| 21127 | 867080 | key_part_end = | |
| 21128 | 867080 | key_part + table->key_info[table->s->primary_key].user_defined_key_parts; | |
| 21129 | |||
| 21130 |
2/2✓ Branch 0 taken 867697 times.
✓ Branch 1 taken 97446 times.
|
965143 | for (; key_part != key_part_end; ++key_part) { |
| 21131 | 867697 | field = key_part->field; | |
| 21132 | 867697 | mysql_type = field->type(); | |
| 21133 | |||
| 21134 |
2/4✓ Branch 0 taken 867697 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 867697 times.
✗ Branch 3 not taken.
|
867697 | if (mysql_type == MYSQL_TYPE_TINY_BLOB || |
| 21135 |
3/4✓ Branch 0 taken 867634 times.
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 867634 times.
|
867697 | mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB || |
| 21136 | mysql_type == MYSQL_TYPE_LONG_BLOB) { | ||
| 21137 | /* In the MySQL key value format, a column prefix of | ||
| 21138 | a BLOB is preceded by a 2-byte length field */ | ||
| 21139 | |||
| 21140 | 63 | len1 = innobase_read_from_2_little_endian(ref1); | |
| 21141 | 63 | len2 = innobase_read_from_2_little_endian(ref2); | |
| 21142 | |||
| 21143 | 63 | result = | |
| 21144 | 63 | down_cast<Field_blob *>(field)->cmp(ref1 + 2, len1, ref2 + 2, len2); | |
| 21145 | } else { | ||
| 21146 | 867634 | result = field->key_cmp(ref1, ref2); | |
| 21147 | } | ||
| 21148 | |||
| 21149 |
2/2✓ Branch 0 taken 769634 times.
✓ Branch 1 taken 98063 times.
|
867697 | if (result) { |
| 21150 | 769634 | return (result); | |
| 21151 | } | ||
| 21152 | |||
| 21153 | 98063 | ref1 += key_part->store_length; | |
| 21154 | 98063 | ref2 += key_part->store_length; | |
| 21155 | } | ||
| 21156 | |||
| 21157 | 97446 | return (0); | |
| 21158 | } | ||
| 21159 | |||
| 21160 | /** This function is used to find the storage length in bytes of the first n | ||
| 21161 | characters for prefix indexes using a multibyte character set. The function | ||
| 21162 | finds charset information and returns length of prefix_len characters in the | ||
| 21163 | index field in bytes. | ||
| 21164 | @return number of bytes occupied by the first n characters */ | ||
| 21165 | 206316 | ulint innobase_get_at_most_n_mbchars( | |
| 21166 | ulint charset_id, /*!< in: character set id */ | ||
| 21167 | ulint prefix_len, /*!< in: prefix length in bytes of the index | ||
| 21168 | (this has to be divided by mbmaxlen to get the | ||
| 21169 | number of CHARACTERS n in the prefix) */ | ||
| 21170 | ulint data_len, /*!< in: length of the string in bytes */ | ||
| 21171 | const char *str) /*!< in: character string */ | ||
| 21172 | { | ||
| 21173 | ulint char_length; /*!< character length in bytes */ | ||
| 21174 | ulint n_chars; /*!< number of characters in prefix */ | ||
| 21175 | CHARSET_INFO *charset; /*!< charset used in the field */ | ||
| 21176 | |||
| 21177 | 206316 | charset = get_charset((uint)charset_id, MYF(MY_WME)); | |
| 21178 | |||
| 21179 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 206322 times.
|
206321 | ut_ad(charset); |
| 21180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 206322 times.
|
206322 | ut_ad(charset->mbmaxlen); |
| 21181 | |||
| 21182 | /* Calculate how many characters at most the prefix index contains */ | ||
| 21183 | |||
| 21184 | 206322 | n_chars = prefix_len / charset->mbmaxlen; | |
| 21185 | |||
| 21186 | /* If the charset is multi-byte, then we must find the length of the | ||
| 21187 | first at most n chars in the string. If the string contains less | ||
| 21188 | characters than n, then we return the length to the end of the last | ||
| 21189 | character. */ | ||
| 21190 | |||
| 21191 |
1/2✓ Branch 0 taken 206322 times.
✗ Branch 1 not taken.
|
206322 | if (charset->mbmaxlen > 1) { |
| 21192 | /* my_charpos() returns the byte length of the first n_chars | ||
| 21193 | characters, or a value bigger than the length of str, if | ||
| 21194 | there were not enough full characters in str. | ||
| 21195 | |||
| 21196 | Why does the code below work: | ||
| 21197 | Suppose that we are looking for n UTF-8 characters. | ||
| 21198 | |||
| 21199 | 1) If the string is long enough, then the prefix contains at | ||
| 21200 | least n complete UTF-8 characters + maybe some extra | ||
| 21201 | characters + an incomplete UTF-8 character. No problem in | ||
| 21202 | this case. The function returns the pointer to the | ||
| 21203 | end of the nth character. | ||
| 21204 | |||
| 21205 | 2) If the string is not long enough, then the string contains | ||
| 21206 | the complete value of a column, that is, only complete UTF-8 | ||
| 21207 | characters, and we can store in the column prefix index the | ||
| 21208 | whole string. */ | ||
| 21209 | |||
| 21210 | 206322 | char_length = my_charpos(charset, str, str + data_len, (int)n_chars); | |
| 21211 |
2/2✓ Branch 0 taken 155133 times.
✓ Branch 1 taken 51196 times.
|
206329 | if (char_length > data_len) { |
| 21212 | 155133 | char_length = data_len; | |
| 21213 | } | ||
| 21214 | ✗ | } else if (data_len < prefix_len) { | |
| 21215 | ✗ | char_length = data_len; | |
| 21216 | |||
| 21217 | } else { | ||
| 21218 | ✗ | char_length = prefix_len; | |
| 21219 | } | ||
| 21220 | |||
| 21221 | 206329 | return (char_length); | |
| 21222 | } | ||
| 21223 | |||
| 21224 | /** This function is used to prepare an X/Open XA distributed transaction. | ||
| 21225 | @return 0 or error number */ | ||
| 21226 | 7283262 | static int innobase_xa_prepare(handlerton *hton, /*!< in: InnoDB handlerton */ | |
| 21227 | THD *thd, /*!< in: handle to the MySQL thread of | ||
| 21228 | the user whose XA transaction should | ||
| 21229 | be prepared */ | ||
| 21230 | bool prepare_trx) /*!< in: true - prepare | ||
| 21231 | transaction false - the current | ||
| 21232 | SQL statement ended */ | ||
| 21233 | { | ||
| 21234 |
1/2✓ Branch 0 taken 7283329 times.
✗ Branch 1 not taken.
|
7283262 | trx_t *trx = check_trx_exists(thd); |
| 21235 | |||
| 21236 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7283329 times.
|
7283329 | assert(hton == innodb_hton_ptr); |
| 21237 | |||
| 21238 |
1/2✓ Branch 0 taken 7283287 times.
✗ Branch 1 not taken.
|
7283329 | thd_get_xid(thd, (MYSQL_XID *)trx->xid); |
| 21239 | |||
| 21240 |
1/2✓ Branch 0 taken 7283312 times.
✗ Branch 1 not taken.
|
7283287 | innobase_srv_conc_force_exit_innodb(trx); |
| 21241 | |||
| 21242 |
1/2✓ Branch 0 taken 7283285 times.
✗ Branch 1 not taken.
|
7283312 | TrxInInnoDB trx_in_innodb(trx); |
| 21243 | |||
| 21244 |
5/6✓ Branch 0 taken 7283326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7283035 times.
✓ Branch 3 taken 291 times.
✓ Branch 4 taken 293 times.
✓ Branch 5 taken 7283024 times.
|
14566311 | if (trx_in_innodb.is_aborted() || |
| 21245 |
3/4✓ Branch 0 taken 7283026 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7283024 times.
|
7283035 | DBUG_EVALUATE_IF("simulate_xa_failure_prepare_in_engine", 1, 0)) { |
| 21246 |
1/2✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
|
293 | innobase_rollback(hton, thd, prepare_trx); |
| 21247 | |||
| 21248 |
1/2✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
|
293 | return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd)); |
| 21249 | } | ||
| 21250 | |||
| 21251 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 7282979 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7282979 times.
|
7283024 | if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { |
| 21252 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_UNREGISTERED_TRX_ACTIVE); | |
| 21253 | } | ||
| 21254 | |||
| 21255 |
4/4✓ Branch 0 taken 6785781 times.
✓ Branch 1 taken 497208 times.
✓ Branch 2 taken 1977525 times.
✓ Branch 3 taken 5305472 times.
|
14068778 | if (prepare_trx || |
| 21256 |
3/4✓ Branch 0 taken 6785789 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1480309 times.
✓ Branch 3 taken 5305480 times.
|
6785781 | (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { |
| 21257 | /* We were instructed to prepare the whole transaction, or | ||
| 21258 | this is an SQL statement end and autocommit is on */ | ||
| 21259 | |||
| 21260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1977536 times.
|
1977525 | ut_ad(trx_is_registered_for_2pc(trx)); |
| 21261 | |||
| 21262 |
1/2✓ Branch 0 taken 1977544 times.
✗ Branch 1 not taken.
|
1977536 | dberr_t err = trx_prepare_for_mysql(trx); |
| 21263 | |||
| 21264 |
4/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1977540 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1977552 times.
|
1977544 | ut_ad(err == DB_SUCCESS || err == DB_FORCED_ABORT); |
| 21265 | |||
| 21266 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1977548 times.
|
1977552 | if (err == DB_FORCED_ABORT) { |
| 21267 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | innobase_rollback(hton, thd, prepare_trx); |
| 21268 | |||
| 21269 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | return (convert_error_code_to_mysql(DB_FORCED_ABORT, 0, thd)); |
| 21270 | } | ||
| 21271 | |||
| 21272 |
4/6✓ Branch 0 taken 1977548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1977545 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
1977548 | DBUG_EXECUTE_IF("crash_innodb_after_prepare", DBUG_SUICIDE();); |
| 21273 | |||
| 21274 | } else { | ||
| 21275 | /* We just mark the SQL statement ended and do not do a | ||
| 21276 | transaction prepare */ | ||
| 21277 | |||
| 21278 | /* If we had reserved the auto-inc lock for some | ||
| 21279 | table in this SQL statement we release it now */ | ||
| 21280 | |||
| 21281 |
1/2✓ Branch 0 taken 5305482 times.
✗ Branch 1 not taken.
|
5305472 | lock_unlock_table_autoinc(trx); |
| 21282 | |||
| 21283 | /* Store the current undo_no of the transaction so that we | ||
| 21284 | know where to roll back if we have to roll back the next | ||
| 21285 | SQL statement */ | ||
| 21286 | |||
| 21287 |
1/2✓ Branch 0 taken 5305484 times.
✗ Branch 1 not taken.
|
5305482 | trx_mark_sql_stat_end(trx); |
| 21288 | } | ||
| 21289 | |||
| 21290 |
5/6✓ Branch 0 taken 7283029 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7282403 times.
✓ Branch 3 taken 626 times.
✓ Branch 4 taken 6785821 times.
✓ Branch 5 taken 496582 times.
|
14068849 | if (thd_sql_command(thd) != SQLCOM_XA_PREPARE && |
| 21291 | 6785820 | (prepare_trx || | |
| 21292 |
3/4✓ Branch 0 taken 6785820 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1480338 times.
✓ Branch 3 taken 5305482 times.
|
6785821 | !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { |
| 21293 | /* For mysqlbackup to work the order of transactions in binlog | ||
| 21294 | and InnoDB must be the same. Consider the situation | ||
| 21295 | |||
| 21296 | thread1> prepare; write to binlog; ... | ||
| 21297 | <context switch> | ||
| 21298 | thread2> prepare; write to binlog; commit | ||
| 21299 | thread1> ... commit | ||
| 21300 | |||
| 21301 | The server guarantees that writes to the binary log | ||
| 21302 | and commits are in the same order, so we do not have | ||
| 21303 | to handle this case. */ | ||
| 21304 | } | ||
| 21305 | |||
| 21306 | 7283028 | return (0); | |
| 21307 | 7283325 | } | |
| 21308 | |||
| 21309 | /** This function is used to recover X/Open XA distributed transactions. | ||
| 21310 | @return number of prepared transactions stored in xid_list */ | ||
| 21311 | 11837 | static int innobase_xa_recover( | |
| 21312 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 21313 | XA_recover_txn *txn_list, /*!< in/out: prepared transactions */ | ||
| 21314 | uint len, /*!< in: number of slots in xid_list */ | ||
| 21315 | MEM_ROOT *mem_root) /*!< in: memory for table names */ | ||
| 21316 | { | ||
| 21317 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11837 times.
|
11837 | assert(hton == innodb_hton_ptr); |
| 21318 | |||
| 21319 |
2/4✓ Branch 0 taken 11837 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11837 times.
|
11837 | if (len == 0 || txn_list == nullptr) { |
| 21320 | ✗ | return (0); | |
| 21321 | } | ||
| 21322 | |||
| 21323 | 11837 | return (trx_recover_for_mysql(txn_list, len, mem_root)); | |
| 21324 | } | ||
| 21325 | |||
| 21326 | 11837 | static int innobase_xa_recover_prepared_in_tc(handlerton *hton, | |
| 21327 | Xa_state_list &xa_list) { | ||
| 21328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11837 times.
|
11837 | assert(hton == innodb_hton_ptr); |
| 21329 | |||
| 21330 | 11837 | return (trx_recover_tc_for_mysql(xa_list)); | |
| 21331 | } | ||
| 21332 | |||
| 21333 | /** This function is used to commit one X/Open XA distributed transaction | ||
| 21334 | which is in the prepared state | ||
| 21335 | @return 0 or error number */ | ||
| 21336 | 619 | static xa_status_code innobase_commit_by_xid( | |
| 21337 | handlerton *hton, XID *xid) /*!< in: X/Open XA transaction identification */ | ||
| 21338 | { | ||
| 21339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 619 times.
|
619 | assert(hton == innodb_hton_ptr); |
| 21340 | |||
| 21341 | 619 | trx_t *trx = trx_get_trx_by_xid(xid); | |
| 21342 | |||
| 21343 |
2/2✓ Branch 0 taken 603 times.
✓ Branch 1 taken 16 times.
|
619 | if (trx != nullptr) { |
| 21344 |
1/2✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
|
603 | TrxInInnoDB trx_in_innodb(trx); |
| 21345 | |||
| 21346 |
1/2✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
|
603 | innobase_commit_low(trx); |
| 21347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 603 times.
|
603 | ut_ad(trx->mysql_thd == nullptr); |
| 21348 | /* use cases are: disconnected xa, slave xa, recovery */ | ||
| 21349 | 603 | trx_deregister_from_2pc(trx); | |
| 21350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 603 times.
|
603 | ut_ad(!trx->will_lock); /* trx cache requirement */ |
| 21351 |
1/2✓ Branch 0 taken 603 times.
✗ Branch 1 not taken.
|
603 | trx_free_for_background(trx); |
| 21352 | |||
| 21353 | 603 | return (XA_OK); | |
| 21354 | 603 | } else { | |
| 21355 | 16 | return (XAER_NOTA); | |
| 21356 | } | ||
| 21357 | } | ||
| 21358 | |||
| 21359 | /** This function is used to rollback one X/Open XA distributed transaction | ||
| 21360 | which is in the prepared state | ||
| 21361 | @return 0 or error number */ | ||
| 21362 | 327 | static xa_status_code innobase_rollback_by_xid( | |
| 21363 | handlerton *hton, /*!< in: InnoDB handlerton */ | ||
| 21364 | XID *xid) /*!< in: X/Open XA transaction | ||
| 21365 | identification */ | ||
| 21366 | { | ||
| 21367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 327 times.
|
327 | assert(hton == innodb_hton_ptr); |
| 21368 | |||
| 21369 | 327 | trx_t *trx = trx_get_trx_by_xid(xid); | |
| 21370 | |||
| 21371 |
2/2✓ Branch 0 taken 312 times.
✓ Branch 1 taken 15 times.
|
327 | if (trx != nullptr) { |
| 21372 |
1/2✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
|
312 | TrxInInnoDB trx_in_innodb(trx); |
| 21373 | |||
| 21374 |
1/2✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
|
312 | int ret = innobase_rollback_trx(trx); |
| 21375 | |||
| 21376 | 312 | trx_deregister_from_2pc(trx); | |
| 21377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
|
312 | ut_ad(!trx->will_lock); |
| 21378 |
1/2✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
|
312 | trx_free_for_background(trx); |
| 21379 | |||
| 21380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 312 times.
|
312 | return (ret != 0 ? XAER_RMERR : XA_OK); |
| 21381 | 312 | } else { | |
| 21382 | 15 | return (XAER_NOTA); | |
| 21383 | } | ||
| 21384 | } | ||
| 21385 | |||
| 21386 | 587 | static int innobase_set_prepared_in_tc(handlerton *hton, THD *thd) { | |
| 21387 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
|
587 | assert(hton == innodb_hton_ptr); |
| 21388 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
|
587 | assert(thd != nullptr); |
| 21389 | |||
| 21390 | 587 | trx_t *trx = check_trx_exists(thd); | |
| 21391 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
|
587 | assert(trx != nullptr); |
| 21392 | |||
| 21393 | 587 | thd_get_xid(thd, (MYSQL_XID *)trx->xid); | |
| 21394 | |||
| 21395 | 587 | innobase_srv_conc_force_exit_innodb(trx); | |
| 21396 | |||
| 21397 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 587 times.
|
587 | ut_ad(trx_is_registered_for_2pc(trx) || thd == nullptr); |
| 21398 | |||
| 21399 | 587 | dberr_t err = trx_set_prepared_in_tc_for_mysql(trx); | |
| 21400 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 587 times.
|
587 | ut_ad(err != DB_FORCED_ABORT); |
| 21401 | |||
| 21402 | 587 | return convert_error_code_to_mysql(err, 0, thd); | |
| 21403 | } | ||
| 21404 | |||
| 21405 | 62 | static xa_status_code innobase_set_prepared_in_tc_by_xid(handlerton *hton, | |
| 21406 | XID *xid) { | ||
| 21407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | assert(hton == innodb_hton_ptr); |
| 21408 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | assert(xid != nullptr); |
| 21409 | |||
| 21410 | 62 | trx_t *trx = trx_get_trx_by_xid(xid); | |
| 21411 | |||
| 21412 |
1/2✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
|
62 | if (trx != nullptr) { |
| 21413 | /* Side effect of retrieving the transaction is XID being set to null */ | ||
| 21414 | 62 | *trx->xid = *xid; | |
| 21415 | |||
| 21416 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 6 times.
|
62 | if (trx_is_prepared_in_tc(trx)) { |
| 21417 | 56 | return XA_OK; | |
| 21418 | } | ||
| 21419 | |||
| 21420 | 6 | innobase_srv_conc_force_exit_innodb(trx); | |
| 21421 | |||
| 21422 | 6 | dberr_t err = trx_set_prepared_in_tc_for_mysql(trx); | |
| 21423 | |||
| 21424 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | ut_ad(err != DB_FORCED_ABORT); |
| 21425 | |||
| 21426 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | return (err != DB_SUCCESS ? XAER_RMERR : XA_OK); |
| 21427 | } else { | ||
| 21428 | ✗ | return (XAER_NOTA); | |
| 21429 | } | ||
| 21430 | } | ||
| 21431 | |||
| 21432 | /** */ | ||
| 21433 | |||
| 21434 | 249 | bool ha_innobase::check_if_incompatible_data(HA_CREATE_INFO *info, | |
| 21435 | uint table_changes) { | ||
| 21436 | 249 | innobase_copy_frm_flags_from_create_info(m_prebuilt->table, info); | |
| 21437 | |||
| 21438 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if (table_changes != IS_EQUAL_YES) { |
| 21439 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 21440 | } | ||
| 21441 | |||
| 21442 | /* Check that auto_increment value was not changed */ | ||
| 21443 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if ((info->used_fields & HA_CREATE_USED_AUTO) && |
| 21444 | ✗ | info->auto_increment_value != 0) { | |
| 21445 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 21446 | } | ||
| 21447 | |||
| 21448 | /* Check that row format didn't change */ | ||
| 21449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if ((info->used_fields & HA_CREATE_USED_ROW_FORMAT) && |
| 21450 | ✗ | info->row_type != table->s->real_row_type) { | |
| 21451 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 21452 | } | ||
| 21453 | |||
| 21454 | /* Specifying KEY_BLOCK_SIZE requests a rebuild of the table. */ | ||
| 21455 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 249 times.
|
249 | if (info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) { |
| 21456 | ✗ | return (COMPATIBLE_DATA_NO); | |
| 21457 | } | ||
| 21458 | |||
| 21459 | 249 | return (COMPATIBLE_DATA_YES); | |
| 21460 | } | ||
| 21461 | |||
| 21462 | /** This function reads zip dict-related info from SYS_ZIP_DICT | ||
| 21463 | and SYS_ZIP_DICT_COLS for all columns marked with | ||
| 21464 | COLUMN_FORMAT_TYPE_COMPRESSED flag and updates | ||
| 21465 | zip_dict_name / zip_dict_data for those which have associated | ||
| 21466 | compression dictionaries. | ||
| 21467 | |||
| 21468 | @param thd Thread handle, used to determine whether it is | ||
| 21469 | necessary to lock dict_sys mutex | ||
| 21470 | @param part_name Full table name (including partition part). | ||
| 21471 | Must be non-NULL only if called from | ||
| 21472 | ha_partition. | ||
| 21473 | */ | ||
| 21474 | 33 | void ha_innobase::upgrade_update_field_with_zip_dict_info( | |
| 21475 | THD *thd, const char *part_name) { | ||
| 21476 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | DBUG_ENTER("upgrade_update_field_with_zip_dict_info"); |
| 21477 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
|
33 | ut_ad(srv_is_upgrade_mode); |
| 21478 | |||
| 21479 | char norm_name[FN_REFLEN]; | ||
| 21480 |
3/4✓ Branch 0 taken 18 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
|
51 | normalize_table_name( |
| 21481 | 18 | norm_name, part_name ? part_name : table_share->normalized_path.str); | |
| 21482 | |||
| 21483 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | const innodb_session_t *const innodb_session = thd_to_innodb_session(thd); |
| 21484 | 33 | bool dict_locked = innodb_session->is_dict_mutex_locked(); | |
| 21485 | |||
| 21486 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | dict_table_t *const ib_table = dict_table_open_on_name( |
| 21487 | norm_name, dict_locked, false, DICT_ERR_IGNORE_NONE); | ||
| 21488 | |||
| 21489 | /* if dict_table_open_on_name() returns NULL, then it means that | ||
| 21490 | TABLE_SHARE is populated for a table being created and we can | ||
| 21491 | skip filling zip dict info here */ | ||
| 21492 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
33 | if (ib_table == nullptr) DBUG_VOID_RETURN; |
| 21493 | |||
| 21494 | 33 | const table_id_t ib_table_id = ib_table->id - DICT_MAX_DD_TABLES; | |
| 21495 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | dict_table_close(ib_table, dict_locked, false); |
| 21496 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 33 times.
|
102 | for (uint i = 0; i < table_share->fields; ++i) { |
| 21497 | 69 | Field *const field = table_share->field[i]; | |
| 21498 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 30 times.
|
69 | if (field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED) { |
| 21499 | 39 | bool reference_found = false; | |
| 21500 | 39 | ulint dict_id = 0; | |
| 21501 |
3/5✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
|
39 | switch (dict_get_dictionary_id_by_key(ib_table_id, i, &dict_id)) { |
| 21502 | 24 | case DB_SUCCESS: | |
| 21503 | 24 | reference_found = true; | |
| 21504 | 24 | break; | |
| 21505 | 15 | case DB_RECORD_NOT_FOUND: | |
| 21506 | 15 | reference_found = false; | |
| 21507 | 15 | break; | |
| 21508 | ✗ | default: | |
| 21509 | ✗ | ut_error; | |
| 21510 | } | ||
| 21511 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 15 times.
|
39 | if (reference_found) { |
| 21512 | 24 | char *local_name = nullptr; | |
| 21513 | 24 | ulint local_name_len = 0; | |
| 21514 | 24 | char *local_data = nullptr; | |
| 21515 | 24 | ulint local_data_len = 0; | |
| 21516 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | if (dict_get_dictionary_info_by_id(dict_id, &local_name, |
| 21517 | &local_name_len, &local_data, | ||
| 21518 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | &local_data_len) != DB_SUCCESS) |
| 21519 | ✗ | ut_error; | |
| 21520 | else { | ||
| 21521 | 24 | field->zip_dict_name.str = local_name; | |
| 21522 | 24 | field->zip_dict_name.length = local_name_len; | |
| 21523 | 24 | field->zip_dict_data.str = local_data; | |
| 21524 | 24 | field->zip_dict_data.length = local_data_len; | |
| 21525 | } | ||
| 21526 | } else { | ||
| 21527 | 15 | field->zip_dict_name.str = nullptr; | |
| 21528 | 15 | field->zip_dict_name.length = 0; | |
| 21529 | 15 | field->zip_dict_data.str = nullptr; | |
| 21530 | 15 | field->zip_dict_data.length = 0; | |
| 21531 | } | ||
| 21532 | } | ||
| 21533 | } | ||
| 21534 |
1/2✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
|
33 | DBUG_VOID_RETURN; |
| 21535 | } | ||
| 21536 | |||
| 21537 | /** Update the system variable innodb_io_capacity_max using the "saved" | ||
| 21538 | value. This function is registered as a callback with MySQL. */ | ||
| 21539 | 10 | static void innodb_io_capacity_max_update( | |
| 21540 | THD *thd, /*!< in: thread handle */ | ||
| 21541 | SYS_VAR *, /*!< in: pointer to | ||
| 21542 | system variable */ | ||
| 21543 | void *, /*!< out: where the | ||
| 21544 | formal string goes */ | ||
| 21545 | const void *save) /*!< in: immediate result | ||
| 21546 | from check function */ | ||
| 21547 | { | ||
| 21548 | 10 | ulong in_val = *static_cast<const ulong *>(save); | |
| 21549 | |||
| 21550 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
|
10 | if (in_val < srv_io_capacity) { |
| 21551 | 2 | in_val = srv_io_capacity; | |
| 21552 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21553 | "innodb_io_capacity_max cannot be" | ||
| 21554 | " set lower than innodb_io_capacity."); | ||
| 21555 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21556 | "Setting innodb_io_capacity_max to %lu", | ||
| 21557 | srv_io_capacity); | ||
| 21558 | } | ||
| 21559 | |||
| 21560 | 10 | srv_max_io_capacity = in_val; | |
| 21561 | 10 | } | |
| 21562 | |||
| 21563 | /** Update the system variable innodb_io_capacity using the "saved" | ||
| 21564 | value. This function is registered as a callback with MySQL. */ | ||
| 21565 | 18 | static void innodb_io_capacity_update( | |
| 21566 | THD *thd, /*!< in: thread handle */ | ||
| 21567 | SYS_VAR *, /*!< in: pointer to system variable */ | ||
| 21568 | void *, /*!< out: where the formal string goes */ | ||
| 21569 | const void *save) /*!< in: immediate result from check function */ | ||
| 21570 | { | ||
| 21571 | 18 | ulong in_val = *static_cast<const ulong *>(save); | |
| 21572 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 17 times.
|
18 | if (in_val > srv_max_io_capacity) { |
| 21573 | 1 | in_val = srv_max_io_capacity; | |
| 21574 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21575 | "innodb_io_capacity cannot be set" | ||
| 21576 | " higher than innodb_io_capacity_max."); | ||
| 21577 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21578 | "Setting innodb_io_capacity to %lu", | ||
| 21579 | srv_max_io_capacity); | ||
| 21580 | } | ||
| 21581 | |||
| 21582 | 18 | srv_io_capacity = in_val; | |
| 21583 | 18 | } | |
| 21584 | |||
| 21585 | /** Update the system variable innodb_max_dirty_pages_pct using the "saved" | ||
| 21586 | value. This function is registered as a callback with MySQL. */ | ||
| 21587 | 36 | static void innodb_max_dirty_pages_pct_update( | |
| 21588 | THD *thd, /*!< in: thread handle */ | ||
| 21589 | SYS_VAR *, /*!< in: pointer to | ||
| 21590 | system variable */ | ||
| 21591 | void *, /*!< out: where the | ||
| 21592 | formal string goes */ | ||
| 21593 | const void *save) /*!< in: immediate result | ||
| 21594 | from check function */ | ||
| 21595 | { | ||
| 21596 | 36 | double in_val = *static_cast<const double *>(save); | |
| 21597 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34 times.
|
36 | if (in_val < srv_max_dirty_pages_pct_lwm) { |
| 21598 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21599 | "innodb_max_dirty_pages_pct cannot be" | ||
| 21600 | " set lower than" | ||
| 21601 | " innodb_max_dirty_pages_pct_lwm."); | ||
| 21602 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21603 | "Lowering" | ||
| 21604 | " innodb_max_dirty_page_pct_lwm to %lf", | ||
| 21605 | in_val); | ||
| 21606 | |||
| 21607 | 2 | srv_max_dirty_pages_pct_lwm = in_val; | |
| 21608 | } | ||
| 21609 | |||
| 21610 | 36 | srv_max_buf_pool_modified_pct = in_val; | |
| 21611 | 36 | } | |
| 21612 | |||
| 21613 | /** Update the system variable innodb_max_dirty_pages_pct_lwm using the | ||
| 21614 | "saved" value. This function is registered as a callback with MySQL. */ | ||
| 21615 | 20 | static void innodb_max_dirty_pages_pct_lwm_update( | |
| 21616 | THD *thd, /*!< in: thread handle */ | ||
| 21617 | SYS_VAR *, /*!< in: pointer to | ||
| 21618 | system variable */ | ||
| 21619 | void *, /*!< out: where the | ||
| 21620 | formal string goes */ | ||
| 21621 | const void *save) /*!< in: immediate result | ||
| 21622 | from check function */ | ||
| 21623 | { | ||
| 21624 | 20 | double in_val = *static_cast<const double *>(save); | |
| 21625 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
|
20 | if (in_val > srv_max_buf_pool_modified_pct) { |
| 21626 | 2 | in_val = srv_max_buf_pool_modified_pct; | |
| 21627 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21628 | "innodb_max_dirty_pages_pct_lwm" | ||
| 21629 | " cannot be set higher than" | ||
| 21630 | " innodb_max_dirty_pages_pct."); | ||
| 21631 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21632 | "Setting innodb_max_dirty_page_pct_lwm" | ||
| 21633 | " to %lf", | ||
| 21634 | in_val); | ||
| 21635 | } | ||
| 21636 | |||
| 21637 | 20 | srv_max_dirty_pages_pct_lwm = in_val; | |
| 21638 | 20 | } | |
| 21639 | |||
| 21640 | 39 | static int innodb_stopword_table_validate(THD *thd, SYS_VAR *, void *save, | |
| 21641 | struct st_mysql_value *value) { | ||
| 21642 | const char *stopword_table_name; | ||
| 21643 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 21644 | 39 | int len = sizeof(buff); | |
| 21645 | 39 | int ret = 1; | |
| 21646 | |||
| 21647 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | ut_a(save != nullptr); |
| 21648 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | ut_a(value != nullptr); |
| 21649 | |||
| 21650 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | stopword_table_name = value->val_str(value, buff, &len); |
| 21651 | |||
| 21652 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
|
39 | if (stopword_table_name != nullptr) { |
| 21653 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
|
25 | if (stopword_table_name == buff) { |
| 21654 | /* Allocate from thd's memroot */ | ||
| 21655 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | stopword_table_name = thd_strmake(thd, stopword_table_name, len); |
| 21656 | } | ||
| 21657 | } | ||
| 21658 | |||
| 21659 | /* Validate the stopword table's (if supplied) existence and | ||
| 21660 | of the right format */ | ||
| 21661 |
7/8✓ Branch 0 taken 25 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 34 times.
✓ Branch 7 taken 5 times.
|
39 | if (!stopword_table_name || fts_valid_stopword_table(stopword_table_name)) { |
| 21662 | 34 | *static_cast<const char **>(save) = stopword_table_name; | |
| 21663 | 34 | ret = 0; | |
| 21664 | } | ||
| 21665 | |||
| 21666 | 39 | return (ret); | |
| 21667 | } | ||
| 21668 | |||
| 21669 | /** | ||
| 21670 | Utility method that checks if user provided valid value. | ||
| 21671 | If yes, then store that in the save variable. | ||
| 21672 | @return 0 on success, 1 on failure. | ||
| 21673 | */ | ||
| 21674 | 1165 | static int check_func_bool(THD *, SYS_VAR *, void *save, | |
| 21675 | st_mysql_value *value) { | ||
| 21676 | int result; | ||
| 21677 |
2/2✓ Branch 0 taken 969 times.
✓ Branch 1 taken 196 times.
|
1165 | if (value->value_type(value) == MYSQL_VALUE_TYPE_STRING) { |
| 21678 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 21679 | 969 | int length = sizeof(buff); | |
| 21680 | |||
| 21681 |
1/2✓ Branch 0 taken 969 times.
✗ Branch 1 not taken.
|
969 | const char *str = value->val_str(value, buff, &length); |
| 21682 | |||
| 21683 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 969 times.
|
973 | if (str == nullptr) return 1; |
| 21684 | |||
| 21685 |
1/2✓ Branch 0 taken 969 times.
✗ Branch 1 not taken.
|
969 | result = find_type(&bool_typelib, str, length, true) - 1; |
| 21686 | |||
| 21687 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 965 times.
|
969 | if (result < 0) return 1; |
| 21688 | } else { | ||
| 21689 | long long tmp; | ||
| 21690 |
2/4✓ Branch 0 taken 196 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 196 times.
|
204 | if (value->val_int(value, &tmp) < 0) return 1; |
| 21691 |
4/4✓ Branch 0 taken 192 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 188 times.
|
196 | if (tmp > 1 || tmp < 0) return 1; |
| 21692 | 188 | result = static_cast<int>(tmp); | |
| 21693 | } | ||
| 21694 | 1153 | *(bool *)save = result ? true : false; | |
| 21695 | 1153 | return 0; | |
| 21696 | } | ||
| 21697 | |||
| 21698 | /** | ||
| 21699 | Utility method that checks if user has correct session administrative | ||
| 21700 | dynamic privileges. | ||
| 21701 | @return 0 on success, 1 on failure. | ||
| 21702 | */ | ||
| 21703 | 990 | static int check_session_admin(THD *thd) { | |
| 21704 | 990 | Security_context *sctx = thd->security_context(); | |
| 21705 | 990 | if (!sctx->has_global_grant(STRING_WITH_LEN("SESSION_VARIABLES_ADMIN")) | |
| 21706 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 987 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 989 times.
|
993 | .first && |
| 21707 | 3 | !sctx->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN")) | |
| 21708 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | .first) { |
| 21709 | 1 | return 1; | |
| 21710 | } | ||
| 21711 | 989 | return 0; | |
| 21712 | } | ||
| 21713 | |||
| 21714 | /** | ||
| 21715 | Check if SESSION_VARIABLES_ADMIN granted. Throw SQL error if not. | ||
| 21716 | We also accept SYSTEM_VARIABLES_ADMIN since it doesn't make a lot of | ||
| 21717 | sense to be allowed to set the global variable and not the session ones. | ||
| 21718 | |||
| 21719 | @param thd the session context | ||
| 21720 | @param var the system variable to set value for | ||
| 21721 | @param save set the updated value | ||
| 21722 | @param value A struct that reads us the values from mysqld | ||
| 21723 | |||
| 21724 | @retval 1 failure | ||
| 21725 | @retval 0 success | ||
| 21726 | */ | ||
| 21727 | 990 | static int innodb_check_session_admin(THD *thd, SYS_VAR *var, void *save, | |
| 21728 | struct st_mysql_value *value) { | ||
| 21729 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 989 times.
|
990 | if (check_session_admin(thd)) { |
| 21730 | 1 | my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), | |
| 21731 | "SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN"); | ||
| 21732 | 1 | return 1; | |
| 21733 | } | ||
| 21734 | 989 | return check_func_bool(thd, var, save, value); | |
| 21735 | } | ||
| 21736 | |||
| 21737 | 5 | static void innodb_srv_buffer_pool_in_core_file_update(THD *, SYS_VAR *, void *, | |
| 21738 | const void *save) { | ||
| 21739 | 5 | srv_buffer_pool_in_core_file = *(bool *)save; | |
| 21740 | 5 | buf_pool_update_madvise(); | |
| 21741 | 5 | } | |
| 21742 | |||
| 21743 | /** Validate the requested buffer pool size. Also, reserve the necessary | ||
| 21744 | memory needed for buffer pool resize. | ||
| 21745 | @param[in] thd thread handle | ||
| 21746 | @param[in] buffer_pool_size buffer pool size value to be validated | ||
| 21747 | @param[out] aligned_buffer_pool_size aligned version of buffer_pool_size | ||
| 21748 | if validation succeeds, else original value passed in | ||
| 21749 | @return true on success, false on failure. | ||
| 21750 | */ | ||
| 21751 | 30 | static bool innodb_buffer_pool_size_validate(THD *thd, | |
| 21752 | longlong buffer_pool_size, | ||
| 21753 | ulint &aligned_buffer_pool_size) { | ||
| 21754 | 30 | os_rmb; | |
| 21755 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 29 times.
|
30 | if (srv_buf_pool_old_size != srv_buf_pool_size) { |
| 21756 | 1 | push_warning(thd, ER_BUFPOOL_RESIZE_INPROGRESS); | |
| 21757 | 1 | return false; | |
| 21758 | } | ||
| 21759 | |||
| 21760 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
29 | if (srv_buf_pool_instances > 1 && |
| 21761 | buffer_pool_size < BUF_POOL_SIZE_THRESHOLD) { | ||
| 21762 | #ifdef UNIV_DEBUG | ||
| 21763 | /* Ignore 1G constraint to enable mulitple instances | ||
| 21764 | for debug and test. */ | ||
| 21765 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (srv_buf_pool_debug) { |
| 21766 | 2 | goto debug_set; | |
| 21767 | } | ||
| 21768 | #endif /* UNIV_DEBUG */ | ||
| 21769 | |||
| 21770 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21771 | "Cannot update innodb_buffer_pool_size" | ||
| 21772 | " to less than 1GB if" | ||
| 21773 | " innodb_buffer_pool_instances > 1."); | ||
| 21774 | ✗ | return false; | |
| 21775 | } | ||
| 21776 | |||
| 21777 | #ifdef UNIV_DEBUG | ||
| 21778 | 27 | debug_set: | |
| 21779 | #endif /* UNIV_DEBUG */ | ||
| 21780 | |||
| 21781 | if constexpr (sizeof(ulint) == 4) { | ||
| 21782 | if (buffer_pool_size > UINT_MAX32) { | ||
| 21783 | push_warning_printf( | ||
| 21784 | thd, Sql_condition::SL_WARNING, ER_WRONG_VALUE_FOR_VAR, | ||
| 21785 | ER_THD(thd, ER_WRONG_VALUE_FOR_VAR), "innodb_buffer_pool_size", | ||
| 21786 | std::to_string(buffer_pool_size).c_str()); | ||
| 21787 | return false; | ||
| 21788 | } | ||
| 21789 | } | ||
| 21790 | |||
| 21791 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
|
29 | if (!innodb_empty_free_list_algorithm_allowed( |
| 21792 | static_cast<srv_empty_free_list_t>(srv_empty_free_list_algorithm), | ||
| 21793 | buffer_pool_size)) { | ||
| 21794 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21795 | "Cannot update innodb_buffer_pool_size to less than " | ||
| 21796 | "20MB per instance with " | ||
| 21797 | "innodb_empty_free_list_algorithm = backoff."); | ||
| 21798 | 1 | return false; | |
| 21799 | } | ||
| 21800 | |||
| 21801 | 28 | aligned_buffer_pool_size = | |
| 21802 | 28 | buf_pool_size_align(static_cast<ulint>(buffer_pool_size)); | |
| 21803 | |||
| 21804 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
|
28 | if (srv_buf_pool_size == static_cast<ulint>(buffer_pool_size)) { |
| 21805 | /* nothing to do */ | ||
| 21806 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
|
25 | } else if (srv_buf_pool_size == aligned_buffer_pool_size) { |
| 21807 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 21808 | "InnoDB: Cannot resize buffer pool to lesser than" | ||
| 21809 | " chunk size of %llu bytes.", | ||
| 21810 | srv_buf_pool_chunk_unit); | ||
| 21811 | } else { | ||
| 21812 | 23 | srv_buf_pool_size = aligned_buffer_pool_size; | |
| 21813 | 23 | os_wmb; | |
| 21814 | |||
| 21815 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
|
23 | if (buffer_pool_size != static_cast<longlong>(aligned_buffer_pool_size)) { |
| 21816 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | push_warning_printf( |
| 21817 | thd, Sql_condition::SL_WARNING, ER_TRUNCATED_WRONG_VALUE, | ||
| 21818 | ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "innodb_buffer_pool_size", | ||
| 21819 | 14 | std::to_string(buffer_pool_size).c_str()); | |
| 21820 | } | ||
| 21821 | } | ||
| 21822 | |||
| 21823 | 28 | return true; | |
| 21824 | } | ||
| 21825 | |||
| 21826 | /** Set the variable tbsp_extend_and_initialize. This function is registered | ||
| 21827 | as a callback to MySQL. | ||
| 21828 | On Linux, the variable tbsp_extend_and_initialize will be set to the value | ||
| 21829 | passed by the user. A warning will be printed that the user is not | ||
| 21830 | allowed to change the value if the server is running on Windows | ||
| 21831 | or other posix implementations. | ||
| 21832 | @param[in] thd thread handle | ||
| 21833 | @param[out] var_ptr value to be set after the validation | ||
| 21834 | @param[in] save value set by the user */ | ||
| 21835 | 19 | static void innodb_extend_and_initialize_update(THD *thd, SYS_VAR *, | |
| 21836 | void *var_ptr, | ||
| 21837 | const void *save) { | ||
| 21838 | 19 | bool extend_and_initialize [[maybe_unused]] = | |
| 21839 | *static_cast<const bool *>(save); | ||
| 21840 | #if !defined(NO_FALLOCATE) && defined(UNIV_LINUX) | ||
| 21841 | 19 | *static_cast<bool *>(var_ptr) = extend_and_initialize; | |
| 21842 | #else /* !NO_FALLOCATE && UNIV_LINUX */ | ||
| 21843 | push_warning_printf(thd, Sql_condition::SL_WARNING, | ||
| 21844 | ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED, | ||
| 21845 | ER_THD(thd, ER_WARN_VAR_VALUE_CHANGE_NOT_SUPPORTED), | ||
| 21846 | "innodb_extend_and_initialize"); | ||
| 21847 | *static_cast<bool *>(var_ptr) = true; | ||
| 21848 | #endif /* !NO_FALLOCATE && UNIV_LINUX */ | ||
| 21849 | 19 | } | |
| 21850 | |||
| 21851 | /** Update the system variable innodb_buffer_pool_size using the "saved" | ||
| 21852 | value. This function is registered as a callback with MySQL. | ||
| 21853 | @param[in] thd thread handle | ||
| 21854 | @param[out] var_ptr where the formal string goes | ||
| 21855 | @param[in] save immediate result from check function */ | ||
| 21856 | 30 | static void innodb_buffer_pool_size_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 21857 | const void *save) { | ||
| 21858 | 30 | longlong requested_buffer_pool_size = *static_cast<const longlong *>(save); | |
| 21859 | 30 | ulint aligned_buffer_pool_size = 0u; | |
| 21860 |
3/4✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 2 times.
|
30 | if (innodb_buffer_pool_size_validate(thd, requested_buffer_pool_size, |
| 21861 | aligned_buffer_pool_size)) { | ||
| 21862 | 28 | snprintf(export_vars.innodb_buffer_pool_resize_status, | |
| 21863 | sizeof(export_vars.innodb_buffer_pool_resize_status), | ||
| 21864 | "Requested to resize buffer pool."); | ||
| 21865 | |||
| 21866 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | os_event_set(srv_buf_resize_event); |
| 21867 | |||
| 21868 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
56 | ib::info(ER_IB_MSG_573) |
| 21869 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | << export_vars.innodb_buffer_pool_resize_status |
| 21870 |
3/6✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
28 | << " (new size: " << aligned_buffer_pool_size << " bytes)"; |
| 21871 | |||
| 21872 | 28 | *static_cast<longlong *>(var_ptr) = aligned_buffer_pool_size; | |
| 21873 | } | ||
| 21874 | 30 | } | |
| 21875 | |||
| 21876 | /** Update the system variable innobase_deadlock_detect using the "saved" value. | ||
| 21877 | Makes sure to "wake up" the dedicated deadlock detector thread if needed. | ||
| 21878 | This function is registered as a callback with MySQL. | ||
| 21879 | @param[in] save immediate result from check function */ | ||
| 21880 | 14 | static void innobase_deadlock_detect_update(THD *, SYS_VAR *, void *, | |
| 21881 | const void *save) { | ||
| 21882 | 14 | innobase_deadlock_detect = *(bool *)save; | |
| 21883 | /* In case deadlock detection was disabled for a long time it could happen | ||
| 21884 | that all clients have deadlocked with each other and thus they stopped | ||
| 21885 | changing the wait-for graph, which in turn causes deadlock detection to not | ||
| 21886 | observe any action and thus it will not search for deadlocks. So if we now | ||
| 21887 | change from OFF to ON we need to "kick-start" the process. It never hurts to | ||
| 21888 | do so, so we do it even if we check from ON to OFF */ | ||
| 21889 | 14 | lock_wait_request_check_for_cycles(); | |
| 21890 | 14 | } | |
| 21891 | |||
| 21892 | /** Check whether valid argument given to "innodb_fts_internal_tbl_name" | ||
| 21893 | This function is registered as a callback with MySQL. | ||
| 21894 | @param[in] thd thread handle | ||
| 21895 | @param[out] save immediate result for update function | ||
| 21896 | @param[in] value incoming string | ||
| 21897 | @return 0 for valid stopword table */ | ||
| 21898 | 32 | static int innodb_internal_table_validate(THD *thd, SYS_VAR *, void *save, | |
| 21899 | struct st_mysql_value *value) { | ||
| 21900 | const char *table_name; | ||
| 21901 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 21902 | 32 | int len = sizeof(buff); | |
| 21903 | 32 | int ret = 1; | |
| 21904 | dict_table_t *user_table; | ||
| 21905 | 32 | MDL_ticket *mdl = nullptr; | |
| 21906 | |||
| 21907 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | ut_a(save != nullptr); |
| 21908 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | ut_a(value != nullptr); |
| 21909 | |||
| 21910 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | table_name = value->val_str(value, buff, &len); |
| 21911 | |||
| 21912 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 24 times.
|
32 | if (!table_name) { |
| 21913 | 8 | *static_cast<const char **>(save) = nullptr; | |
| 21914 | 8 | return (0); | |
| 21915 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | } else if (table_name == buff) { |
| 21916 | /* Allocate memory from thd's mem_root */ | ||
| 21917 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | table_name = thd_strmake(thd, table_name, len); |
| 21918 | } | ||
| 21919 | |||
| 21920 | /* If name is longer than NAME_LEN, no need to try to open it */ | ||
| 21921 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | if (len >= NAME_LEN) { |
| 21922 | 2 | return (1); | |
| 21923 | } | ||
| 21924 | |||
| 21925 | user_table = | ||
| 21926 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | dd_table_open_on_name(thd, &mdl, table_name, false, DICT_ERR_IGNORE_NONE); |
| 21927 | |||
| 21928 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
|
22 | if (user_table) { |
| 21929 |
3/4✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 1 times.
|
21 | if (dict_table_has_fts_index(user_table)) { |
| 21930 | 20 | *static_cast<const char **>(save) = table_name; | |
| 21931 | 20 | ret = 0; | |
| 21932 | } | ||
| 21933 | |||
| 21934 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | dd_table_close(user_table, thd, &mdl, false); |
| 21935 | |||
| 21936 |
6/10✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
21 | DBUG_EXECUTE_IF("innodb_evict_autoinc_table", dict_sys_mutex_enter(); |
| 21937 | dict_table_remove_from_cache_debug(user_table, true); | ||
| 21938 | dict_sys_mutex_exit();); | ||
| 21939 | } | ||
| 21940 | |||
| 21941 | 22 | return (ret); | |
| 21942 | } | ||
| 21943 | |||
| 21944 | /** Update the system variable innodb_adaptive_hash_index using the "saved" | ||
| 21945 | value. This function is registered as a callback with MySQL. */ | ||
| 21946 | 17 | static void innodb_adaptive_hash_index_update( | |
| 21947 | THD *, /*!< in: thread handle */ | ||
| 21948 | SYS_VAR *, /*!< in: pointer to | ||
| 21949 | system variable */ | ||
| 21950 | void *, /*!< out: where the | ||
| 21951 | formal string goes */ | ||
| 21952 | const void *save) /*!< in: immediate result | ||
| 21953 | from check function */ | ||
| 21954 | { | ||
| 21955 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 6 times.
|
17 | if (*(bool *)save) { |
| 21956 | 11 | btr_search_enable(true); | |
| 21957 | } else { | ||
| 21958 | 6 | btr_search_disable(true); | |
| 21959 | } | ||
| 21960 | 17 | } | |
| 21961 | |||
| 21962 | /** Update the system variable innodb_cmp_per_index using the "saved" | ||
| 21963 | value. This function is registered as a callback with MySQL. */ | ||
| 21964 | 75 | static void innodb_cmp_per_index_update( | |
| 21965 | THD *, /*!< in: thread handle */ | ||
| 21966 | SYS_VAR *, /*!< in: pointer to | ||
| 21967 | system variable */ | ||
| 21968 | void *, /*!< out: where the | ||
| 21969 | formal string goes */ | ||
| 21970 | const void *save) /*!< in: immediate result | ||
| 21971 | from check function */ | ||
| 21972 | { | ||
| 21973 | /* Reset the stats whenever we enable the table | ||
| 21974 | INFORMATION_SCHEMA.innodb_cmp_per_index. */ | ||
| 21975 |
4/4✓ Branch 0 taken 40 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 4 times.
|
75 | if (!srv_cmp_per_index_enabled && *(bool *)save) { |
| 21976 | 36 | page_zip_reset_stat_per_index(); | |
| 21977 | } | ||
| 21978 | |||
| 21979 | 75 | srv_cmp_per_index_enabled = *(bool *)save; | |
| 21980 | 75 | } | |
| 21981 | |||
| 21982 | /** Update the system variable innodb_old_blocks_pct using the "saved" | ||
| 21983 | value. This function is registered as a callback with MySQL. */ | ||
| 21984 | 11 | static void innodb_old_blocks_pct_update( | |
| 21985 | THD *, /*!< in: thread handle */ | ||
| 21986 | SYS_VAR *, /*!< in: pointer to | ||
| 21987 | system variable */ | ||
| 21988 | void *, /*!< out: where the | ||
| 21989 | formal string goes */ | ||
| 21990 | const void *save) /*!< in: immediate result | ||
| 21991 | from check function */ | ||
| 21992 | { | ||
| 21993 | 11 | innobase_old_blocks_pct = static_cast<uint>( | |
| 21994 | 11 | buf_LRU_old_ratio_update(*static_cast<const uint *>(save), true)); | |
| 21995 | 11 | } | |
| 21996 | |||
| 21997 | /** Update the system variable innodb_old_blocks_pct using the "saved" | ||
| 21998 | value. This function is registered as a callback with MySQL. */ | ||
| 21999 | 12 | static void innodb_change_buffer_max_size_update( | |
| 22000 | THD *, /*!< in: thread handle */ | ||
| 22001 | SYS_VAR *, /*!< in: pointer to | ||
| 22002 | system variable */ | ||
| 22003 | void *, /*!< out: where the | ||
| 22004 | formal string goes */ | ||
| 22005 | const void *save) /*!< in: immediate result | ||
| 22006 | from check function */ | ||
| 22007 | { | ||
| 22008 | 12 | srv_change_buffer_max_size = (*static_cast<const uint *>(save)); | |
| 22009 | 12 | ibuf_max_size_update(srv_change_buffer_max_size); | |
| 22010 | 12 | } | |
| 22011 | |||
| 22012 | #ifdef UNIV_DEBUG | ||
| 22013 | static ulong srv_fil_make_page_dirty_debug = 0; | ||
| 22014 | static ulong srv_saved_page_number_debug = 0; | ||
| 22015 | |||
| 22016 | /** Save an InnoDB page number. */ | ||
| 22017 | 61 | static void innodb_save_page_no(THD *, /*!< in: thread handle */ | |
| 22018 | SYS_VAR *, /*!< in: pointer to | ||
| 22019 | system variable */ | ||
| 22020 | void *, /*!< out: where the | ||
| 22021 | formal string goes */ | ||
| 22022 | const void *save) /*!< in: immediate result | ||
| 22023 | from check function */ | ||
| 22024 | { | ||
| 22025 | 61 | srv_saved_page_number_debug = *static_cast<const ulong *>(save); | |
| 22026 | |||
| 22027 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
122 | ib::info(ER_IB_MSG_1257) << "Saving InnoDB page number: " |
| 22028 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
61 | << srv_saved_page_number_debug; |
| 22029 | 61 | } | |
| 22030 | |||
| 22031 | /** Make the first page of given user tablespace dirty. */ | ||
| 22032 | 57 | static void innodb_make_page_dirty(THD *, /*!< in: thread handle */ | |
| 22033 | SYS_VAR *, /*!< in: pointer to | ||
| 22034 | system variable */ | ||
| 22035 | void *, /*!< out: where the | ||
| 22036 | formal string goes */ | ||
| 22037 | const void *save) /*!< in: immediate result | ||
| 22038 | from check function */ | ||
| 22039 | { | ||
| 22040 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | mtr_t mtr; |
| 22041 | 57 | ulong space_id = *static_cast<const ulong *>(save); | |
| 22042 | 57 | page_no_t page_no = srv_saved_page_number_debug; | |
| 22043 | |||
| 22044 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | fil_space_t *space = fil_space_acquire_silent(space_id); |
| 22045 | |||
| 22046 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 52 times.
|
57 | if (space == nullptr) { |
| 22047 | 5 | return; | |
| 22048 | } | ||
| 22049 | |||
| 22050 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50 times.
|
52 | if (page_no > space->size) { |
| 22051 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | fil_space_release(space); |
| 22052 | 2 | return; | |
| 22053 | } | ||
| 22054 | |||
| 22055 | 50 | auto page_id = page_id_t{space->id, page_no}; | |
| 22056 | |||
| 22057 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | mtr.start(); |
| 22058 | |||
| 22059 |
2/4✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
50 | buf_block_t *block = buf_page_get(page_id, page_size_t(space->flags), |
| 22060 | RW_X_LATCH, UT_LOCATION_HERE, &mtr); | ||
| 22061 | |||
| 22062 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | if (block != nullptr) { |
| 22063 | 50 | byte *page = block->frame; | |
| 22064 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | page_type_t page_type = fil_page_get_type(page); |
| 22065 | |||
| 22066 | /* Don't dirty a page that is not yet used. */ | ||
| 22067 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1 times.
|
50 | if (page_type != FIL_PAGE_TYPE_ALLOCATED) { |
| 22068 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
49 | ib::info(ER_IB_MSG_574) |
| 22069 |
2/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
49 | << "Dirtying page: " << page_id |
| 22070 |
2/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
|
49 | << ", page_type=" << fil_get_page_type_str(page_type); |
| 22071 | |||
| 22072 | 49 | dblwr::Force_crash = page_id; | |
| 22073 | |||
| 22074 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
49 | mlog_write_ulint(page + FIL_PAGE_TYPE, page_type, MLOG_2BYTES, &mtr); |
| 22075 | } | ||
| 22076 | } | ||
| 22077 | |||
| 22078 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | mtr.commit(); |
| 22079 | |||
| 22080 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | fil_space_release(space); |
| 22081 | |||
| 22082 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | if (block != nullptr) { |
| 22083 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
50 | buf_flush_sync_all_buf_pools(); |
| 22084 | } | ||
| 22085 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
|
9 | } |
| 22086 | #endif // UNIV_DEBUG | ||
| 22087 | |||
| 22088 | /** Update the monitor counter according to the "set_option", turn | ||
| 22089 | on/off or reset specified monitor counter. */ | ||
| 22090 | 9634 | static void innodb_monitor_set_option( | |
| 22091 | const monitor_info_t *monitor_info, /*!< in: monitor info for the monitor | ||
| 22092 | to set */ | ||
| 22093 | mon_option_t set_option) /*!< in: Turn on/off reset the | ||
| 22094 | counter */ | ||
| 22095 | { | ||
| 22096 | 9634 | monitor_id_t monitor_id = monitor_info->monitor_id; | |
| 22097 | |||
| 22098 | /* If module type is MONITOR_GROUP_MODULE, it cannot be | ||
| 22099 | turned on/off individually. It should never use this | ||
| 22100 | function to set options */ | ||
| 22101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9634 times.
|
9634 | ut_a(!(monitor_info->monitor_type & MONITOR_GROUP_MODULE)); |
| 22102 | |||
| 22103 |
4/5✓ Branch 0 taken 5981 times.
✓ Branch 1 taken 3317 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 294 times.
✗ Branch 4 not taken.
|
9634 | switch (set_option) { |
| 22104 | 5981 | case MONITOR_TURN_ON: | |
| 22105 | 5981 | MONITOR_ON(monitor_id); | |
| 22106 |
4/6✓ Branch 0 taken 14 times.
✓ Branch 1 taken 5967 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
|
5981 | MONITOR_INIT(monitor_id); |
| 22107 | 5981 | MONITOR_SET_START(monitor_id); | |
| 22108 | |||
| 22109 | /* If the monitor to be turned on uses | ||
| 22110 | existing monitor counter (status variable), | ||
| 22111 | make special processing to remember existing | ||
| 22112 | counter value. */ | ||
| 22113 |
2/2✓ Branch 0 taken 3152 times.
✓ Branch 1 taken 2829 times.
|
5981 | if (monitor_info->monitor_type & MONITOR_EXISTING) { |
| 22114 | 3152 | srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_ON); | |
| 22115 | } | ||
| 22116 | |||
| 22117 |
2/2✓ Branch 0 taken 189 times.
✓ Branch 1 taken 5792 times.
|
5981 | if (MONITOR_IS_ON(MONITOR_LATCHES)) { |
| 22118 | 189 | mutex_monitor->enable(); | |
| 22119 | } | ||
| 22120 | 5981 | break; | |
| 22121 | |||
| 22122 | 3317 | case MONITOR_TURN_OFF: | |
| 22123 |
2/2✓ Branch 0 taken 988 times.
✓ Branch 1 taken 2329 times.
|
3317 | if (monitor_info->monitor_type & MONITOR_EXISTING) { |
| 22124 | 988 | srv_mon_process_existing_counter(monitor_id, MONITOR_TURN_OFF); | |
| 22125 | } | ||
| 22126 | |||
| 22127 | 3317 | MONITOR_OFF(monitor_id); | |
| 22128 | 3317 | MONITOR_SET_OFF(monitor_id); | |
| 22129 | |||
| 22130 |
2/2✓ Branch 0 taken 402 times.
✓ Branch 1 taken 2915 times.
|
3317 | if (!MONITOR_IS_ON(MONITOR_LATCHES)) { |
| 22131 | 402 | mutex_monitor->disable(); | |
| 22132 | } | ||
| 22133 | 3317 | break; | |
| 22134 | |||
| 22135 | 42 | case MONITOR_RESET_VALUE: | |
| 22136 | 42 | srv_mon_reset(monitor_id); | |
| 22137 | |||
| 22138 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
|
42 | if (monitor_id == (MONITOR_LATCHES)) { |
| 22139 | 2 | mutex_monitor->reset(); | |
| 22140 | } | ||
| 22141 | 42 | break; | |
| 22142 | |||
| 22143 | 294 | case MONITOR_RESET_ALL_VALUE: | |
| 22144 | 294 | srv_mon_reset_all(monitor_id); | |
| 22145 | 294 | mutex_monitor->reset(); | |
| 22146 | 294 | break; | |
| 22147 | |||
| 22148 | ✗ | default: | |
| 22149 | ✗ | ut_error; | |
| 22150 | } | ||
| 22151 | 9634 | } | |
| 22152 | |||
| 22153 | /** Find matching InnoDB monitor counters and update their status | ||
| 22154 | according to the "set_option", turn on/off or reset specified | ||
| 22155 | monitor counter. */ | ||
| 22156 | 53 | static void innodb_monitor_update_wildcard( | |
| 22157 | const char *name, /*!< in: monitor name to match */ | ||
| 22158 | mon_option_t set_option) /*!< in: the set option, whether | ||
| 22159 | to turn on/off or reset the counter */ | ||
| 22160 | { | ||
| 22161 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
|
53 | ut_a(name); |
| 22162 | |||
| 22163 |
2/2✓ Branch 0 taken 18126 times.
✓ Branch 1 taken 53 times.
|
18179 | for (ulint use = 0; use < NUM_MONITOR; use++) { |
| 22164 | ulint type; | ||
| 22165 | 18126 | monitor_id_t monitor_id = static_cast<monitor_id_t>(use); | |
| 22166 | monitor_info_t *monitor_info; | ||
| 22167 | |||
| 22168 |
2/2✓ Branch 0 taken 8541 times.
✓ Branch 1 taken 9585 times.
|
18126 | if (!innobase_wildcasecmp(srv_mon_get_name(monitor_id), name)) { |
| 22169 | 8541 | monitor_info = srv_mon_get_info(monitor_id); | |
| 22170 | |||
| 22171 | 8541 | type = monitor_info->monitor_type; | |
| 22172 | |||
| 22173 | /* If the monitor counter is of MONITOR_MODULE | ||
| 22174 | type, skip it. Except for those also marked with | ||
| 22175 | MONITOR_GROUP_MODULE flag, which can be turned | ||
| 22176 | on only as a module. */ | ||
| 22177 |
4/4✓ Branch 0 taken 8002 times.
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 7151 times.
✓ Branch 3 taken 851 times.
|
8541 | if (!(type & MONITOR_MODULE) && !(type & MONITOR_GROUP_MODULE)) { |
| 22178 | 7151 | innodb_monitor_set_option(monitor_info, set_option); | |
| 22179 | } | ||
| 22180 | |||
| 22181 | /* Need to special handle counters marked with | ||
| 22182 | MONITOR_GROUP_MODULE, turn on the whole module if | ||
| 22183 | any one of it comes here. Currently, only | ||
| 22184 | "module_buf_page" is marked with MONITOR_GROUP_MODULE */ | ||
| 22185 |
2/2✓ Branch 0 taken 874 times.
✓ Branch 1 taken 7667 times.
|
8541 | if (type & MONITOR_GROUP_MODULE) { |
| 22186 |
1/2✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
|
874 | if ((monitor_id >= MONITOR_MODULE_BUF_PAGE) && |
| 22187 |
1/2✓ Branch 0 taken 874 times.
✗ Branch 1 not taken.
|
874 | (monitor_id < MONITOR_MODULE_OS)) { |
| 22188 |
2/2✓ Branch 0 taken 418 times.
✓ Branch 1 taken 456 times.
|
874 | if (set_option == MONITOR_TURN_ON && |
| 22189 |
2/2✓ Branch 0 taken 407 times.
✓ Branch 1 taken 11 times.
|
418 | MONITOR_IS_ON(MONITOR_MODULE_BUF_PAGE)) { |
| 22190 | 407 | continue; | |
| 22191 | } | ||
| 22192 | |||
| 22193 | 467 | srv_mon_set_module_control(MONITOR_MODULE_BUF_PAGE, set_option); | |
| 22194 | } else { | ||
| 22195 | /* If new monitor is added with | ||
| 22196 | MONITOR_GROUP_MODULE, it needs | ||
| 22197 | to be added here. */ | ||
| 22198 | ✗ | ut_d(ut_error); | |
| 22199 | } | ||
| 22200 | } | ||
| 22201 | } | ||
| 22202 | } | ||
| 22203 | 53 | } | |
| 22204 | |||
| 22205 | /** Given a configuration variable name, find corresponding monitor counter | ||
| 22206 | and return its monitor ID if found. | ||
| 22207 | @return monitor ID if found, MONITOR_NO_MATCH if there is no match */ | ||
| 22208 | 5564 | static ulint innodb_monitor_id_by_name_get( | |
| 22209 | const char *name) /*!< in: monitor counter namer */ | ||
| 22210 | { | ||
| 22211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5564 times.
|
5564 | ut_a(name); |
| 22212 | |||
| 22213 | /* Search for wild character '%' in the name, if | ||
| 22214 | found, we treat it as a wildcard match. We do not search for | ||
| 22215 | single character wildcard '_' since our monitor names already contain | ||
| 22216 | such character. To avoid confusion, we request user must include | ||
| 22217 | at least one '%' character to activate the wildcard search. */ | ||
| 22218 |
2/2✓ Branch 0 taken 111 times.
✓ Branch 1 taken 5453 times.
|
5564 | if (strchr(name, '%')) { |
| 22219 | 111 | return (MONITOR_WILDCARD_MATCH); | |
| 22220 | } | ||
| 22221 | |||
| 22222 | /* Not wildcard match, check for an exact match */ | ||
| 22223 |
2/2✓ Branch 0 taken 924170 times.
✓ Branch 1 taken 15 times.
|
924185 | for (ulint i = 0; i < NUM_MONITOR; i++) { |
| 22224 |
2/2✓ Branch 0 taken 5438 times.
✓ Branch 1 taken 918732 times.
|
924170 | if (!innobase_strcasecmp(name, |
| 22225 | srv_mon_get_name(static_cast<monitor_id_t>(i)))) { | ||
| 22226 | 5438 | return (i); | |
| 22227 | } | ||
| 22228 | } | ||
| 22229 | |||
| 22230 | 15 | return (MONITOR_NO_MATCH); | |
| 22231 | } | ||
| 22232 | /** Validate that the passed in monitor name matches at least one | ||
| 22233 | monitor counter name with wildcard compare. | ||
| 22234 | @return true if at least one monitor name matches */ | ||
| 22235 | 58 | static bool innodb_monitor_validate_wildcard_name( | |
| 22236 | const char *name) /*!< in: monitor counter namer */ | ||
| 22237 | { | ||
| 22238 |
2/2✓ Branch 0 taken 5833 times.
✓ Branch 1 taken 5 times.
|
5838 | for (ulint i = 0; i < NUM_MONITOR; i++) { |
| 22239 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 5780 times.
|
5833 | if (!innobase_wildcasecmp(srv_mon_get_name(static_cast<monitor_id_t>(i)), |
| 22240 | name)) { | ||
| 22241 | 53 | return true; | |
| 22242 | } | ||
| 22243 | } | ||
| 22244 | |||
| 22245 | 5 | return false; | |
| 22246 | } | ||
| 22247 | /** Validate the passed in monitor name, find and save the | ||
| 22248 | corresponding monitor name in the function parameter "save". | ||
| 22249 | @return 0 if monitor name is valid */ | ||
| 22250 | 2792 | static int innodb_monitor_valid_byname( | |
| 22251 | void *save, /*!< out: immediate result | ||
| 22252 | for update function */ | ||
| 22253 | const char *name) /*!< in: incoming monitor name */ | ||
| 22254 | { | ||
| 22255 | ulint use; | ||
| 22256 | monitor_info_t *monitor_info; | ||
| 22257 | |||
| 22258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2792 times.
|
2792 | if (!name) { |
| 22259 | ✗ | return (1); | |
| 22260 | } | ||
| 22261 | |||
| 22262 | 2792 | use = innodb_monitor_id_by_name_get(name); | |
| 22263 | |||
| 22264 | /* No monitor name matches, nor it is wildcard match */ | ||
| 22265 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 2777 times.
|
2792 | if (use == MONITOR_NO_MATCH) { |
| 22266 | 15 | return (1); | |
| 22267 | } | ||
| 22268 | |||
| 22269 |
2/2✓ Branch 0 taken 2719 times.
✓ Branch 1 taken 58 times.
|
2777 | if (use < NUM_MONITOR) { |
| 22270 | 2719 | monitor_info = srv_mon_get_info((monitor_id_t)use); | |
| 22271 | |||
| 22272 | /* If the monitor counter is marked with | ||
| 22273 | MONITOR_GROUP_MODULE flag, then this counter | ||
| 22274 | cannot be turned on/off individually, instead | ||
| 22275 | it shall be turned on/off as a group using | ||
| 22276 | its module name */ | ||
| 22277 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2715 times.
|
2719 | if ((monitor_info->monitor_type & MONITOR_GROUP_MODULE) && |
| 22278 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | (!(monitor_info->monitor_type & MONITOR_MODULE))) { |
| 22279 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_USE_MONITOR_GROUP_NAME, name); | |
| 22280 | ✗ | return (1); | |
| 22281 | } | ||
| 22282 | |||
| 22283 | } else { | ||
| 22284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | ut_a(use == MONITOR_WILDCARD_MATCH); |
| 22285 | |||
| 22286 | /* For wildcard match, if there is not a single monitor | ||
| 22287 | counter name that matches, treat it as an invalid | ||
| 22288 | value for the system configuration variables */ | ||
| 22289 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 53 times.
|
58 | if (!innodb_monitor_validate_wildcard_name(name)) { |
| 22290 | 5 | return (1); | |
| 22291 | } | ||
| 22292 | } | ||
| 22293 | |||
| 22294 | /* Save the configure name for innodb_monitor_update() */ | ||
| 22295 | 2772 | *static_cast<const char **>(save) = name; | |
| 22296 | |||
| 22297 | 2772 | return (0); | |
| 22298 | } | ||
| 22299 | /** Validate passed-in "value" is a valid monitor counter name. | ||
| 22300 | This function is registered as a callback with MySQL. | ||
| 22301 | @return 0 for valid name */ | ||
| 22302 | 2798 | static int innodb_monitor_validate( | |
| 22303 | THD *, /*!< in: thread handle */ | ||
| 22304 | SYS_VAR *, /*!< in: pointer to system | ||
| 22305 | variable */ | ||
| 22306 | void *save, /*!< out: immediate result | ||
| 22307 | for update function */ | ||
| 22308 | struct st_mysql_value *value) /*!< in: incoming string */ | ||
| 22309 | { | ||
| 22310 | const char *name; | ||
| 22311 | char *monitor_name; | ||
| 22312 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 22313 | 2798 | int len = sizeof(buff); | |
| 22314 | int ret; | ||
| 22315 | |||
| 22316 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2798 times.
|
2798 | ut_a(save != nullptr); |
| 22317 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2798 times.
|
2798 | ut_a(value != nullptr); |
| 22318 | |||
| 22319 |
1/2✓ Branch 0 taken 2798 times.
✗ Branch 1 not taken.
|
2798 | name = value->val_str(value, buff, &len); |
| 22320 | |||
| 22321 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2794 times.
|
2798 | if (name == nullptr) { |
| 22322 | 4 | return (1); | |
| 22323 | } | ||
| 22324 | |||
| 22325 | /* Check if the value is a valid string. */ | ||
| 22326 | size_t valid_len; | ||
| 22327 | bool len_error; | ||
| 22328 |
3/4✓ Branch 0 taken 2794 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2790 times.
|
2794 | if (validate_string(system_charset_info, name, len, &valid_len, &len_error)) { |
| 22329 | 4 | return (1); | |
| 22330 | } | ||
| 22331 | |||
| 22332 | /* monitor_name could point to memory from MySQL | ||
| 22333 | or buff[]. Always dup the name to memory allocated | ||
| 22334 | by InnoDB, so we can access it in another callback | ||
| 22335 | function innodb_monitor_update() and free it appropriately */ | ||
| 22336 |
1/2✓ Branch 0 taken 2790 times.
✗ Branch 1 not taken.
|
2790 | if (name) { |
| 22337 |
1/2✓ Branch 0 taken 2790 times.
✗ Branch 1 not taken.
|
2790 | monitor_name = my_strdup(PSI_INSTRUMENT_ME, name, MYF(0)); |
| 22338 | } else { | ||
| 22339 | ✗ | return (1); | |
| 22340 | } | ||
| 22341 | |||
| 22342 |
1/2✓ Branch 0 taken 2790 times.
✗ Branch 1 not taken.
|
2790 | ret = innodb_monitor_valid_byname(save, monitor_name); |
| 22343 | |||
| 22344 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2770 times.
|
2790 | if (ret) { |
| 22345 | /* Validation failed */ | ||
| 22346 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
20 | my_free(monitor_name); |
| 22347 | } else { | ||
| 22348 | /* monitor_name will be freed in separate callback function | ||
| 22349 | innodb_monitor_update(). Assert "save" point to | ||
| 22350 | the "monitor_name" variable */ | ||
| 22351 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2770 times.
|
2770 | ut_ad(*static_cast<char **>(save) == monitor_name); |
| 22352 | } | ||
| 22353 | |||
| 22354 | 2790 | return (ret); | |
| 22355 | } | ||
| 22356 | |||
| 22357 | /** Update the system variable innodb_enable(disable/reset/reset_all)_monitor | ||
| 22358 | according to the "set_option" and turn on/off or reset specified monitor | ||
| 22359 | counter. */ | ||
| 22360 | 2898 | static void innodb_monitor_update( | |
| 22361 | THD *thd, /*!< in: thread handle */ | ||
| 22362 | void *var_ptr, /*!< out: where the | ||
| 22363 | formal string goes */ | ||
| 22364 | const void *save, /*!< in: immediate result | ||
| 22365 | from check function */ | ||
| 22366 | mon_option_t set_option, /*!< in: the set option, | ||
| 22367 | whether to turn on/off or | ||
| 22368 | reset the counter */ | ||
| 22369 | bool free_mem) /*!< in: whether we will | ||
| 22370 | need to free the memory */ | ||
| 22371 | { | ||
| 22372 | monitor_info_t *monitor_info; | ||
| 22373 | ulint monitor_id; | ||
| 22374 | 2898 | ulint err_monitor = 0; | |
| 22375 | const char *name; | ||
| 22376 | |||
| 22377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2898 times.
|
2898 | ut_a(save != nullptr); |
| 22378 | |||
| 22379 | 2898 | name = *static_cast<const char *const *>(save); | |
| 22380 | |||
| 22381 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 2772 times.
|
2898 | if (!name) { |
| 22382 | 126 | monitor_id = MONITOR_DEFAULT_START; | |
| 22383 | } else { | ||
| 22384 | 2772 | monitor_id = innodb_monitor_id_by_name_get(name); | |
| 22385 | |||
| 22386 | /* Double check we have a valid monitor ID */ | ||
| 22387 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2772 times.
|
2772 | if (monitor_id == MONITOR_NO_MATCH) { |
| 22388 | ✗ | return; | |
| 22389 | } | ||
| 22390 | } | ||
| 22391 | |||
| 22392 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 2772 times.
|
2898 | if (monitor_id == MONITOR_DEFAULT_START) { |
| 22393 | /* If user set the variable to "default", we will | ||
| 22394 | print a message and make this set operation a "noop". | ||
| 22395 | The check is being made here is because "set default" | ||
| 22396 | does not go through validation function */ | ||
| 22397 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | if (thd) { |
| 22398 | 126 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_NO_DEFAULT, | |
| 22399 | "Default value is not defined for" | ||
| 22400 | " this set option. Please specify" | ||
| 22401 | " correct counter or module name."); | ||
| 22402 | } else { | ||
| 22403 | ✗ | log_errlog(ERROR_LEVEL, ER_INNODB_MONITOR_DEFAULT_VALUE_NOT_DEFINED); | |
| 22404 | } | ||
| 22405 | |||
| 22406 |
1/2✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
|
126 | if (var_ptr) { |
| 22407 | 126 | *(const char **)var_ptr = nullptr; | |
| 22408 | } | ||
| 22409 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 2719 times.
|
2772 | } else if (monitor_id == MONITOR_WILDCARD_MATCH) { |
| 22410 | 53 | innodb_monitor_update_wildcard(name, set_option); | |
| 22411 | } else { | ||
| 22412 | 2719 | monitor_info = srv_mon_get_info(static_cast<monitor_id_t>(monitor_id)); | |
| 22413 | |||
| 22414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2719 times.
|
2719 | ut_a(monitor_info); |
| 22415 | |||
| 22416 | /* If monitor is already truned on, someone could already | ||
| 22417 | collect monitor data, exit and ask user to turn off the | ||
| 22418 | monitor before turn it on again. */ | ||
| 22419 |
4/4✓ Branch 0 taken 2431 times.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2427 times.
|
2719 | if (set_option == MONITOR_TURN_ON && MONITOR_IS_ON(monitor_id)) { |
| 22420 | 4 | err_monitor = monitor_id; | |
| 22421 | 4 | goto exit; | |
| 22422 | } | ||
| 22423 | |||
| 22424 |
2/2✓ Branch 0 taken 2713 times.
✓ Branch 1 taken 2 times.
|
2715 | if (var_ptr) { |
| 22425 | 2713 | *(const char **)var_ptr = monitor_info->monitor_name; | |
| 22426 | } | ||
| 22427 | |||
| 22428 | /* Depending on the monitor name is for a module or | ||
| 22429 | a counter, process counters in the whole module or | ||
| 22430 | individual counter. */ | ||
| 22431 |
2/2✓ Branch 0 taken 232 times.
✓ Branch 1 taken 2483 times.
|
2715 | if (monitor_info->monitor_type & MONITOR_MODULE) { |
| 22432 | 232 | srv_mon_set_module_control(static_cast<monitor_id_t>(monitor_id), | |
| 22433 | set_option); | ||
| 22434 | } else { | ||
| 22435 | 2483 | innodb_monitor_set_option(monitor_info, set_option); | |
| 22436 | } | ||
| 22437 | } | ||
| 22438 | 2898 | exit: | |
| 22439 | /* Only if we are trying to turn on a monitor that already | ||
| 22440 | been turned on, we will set err_monitor. Print related | ||
| 22441 | information */ | ||
| 22442 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2894 times.
|
2898 | if (err_monitor) { |
| 22443 | 4 | log_errlog(WARNING_LEVEL, ER_INNODB_MONITOR_IS_ENABLED, | |
| 22444 | srv_mon_get_name((monitor_id_t)err_monitor)); | ||
| 22445 | } | ||
| 22446 | |||
| 22447 |
4/4✓ Branch 0 taken 2896 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2770 times.
✓ Branch 3 taken 126 times.
|
2898 | if (free_mem && name) { |
| 22448 | 2770 | my_free((void *)name); | |
| 22449 | } | ||
| 22450 | |||
| 22451 | 2898 | return; | |
| 22452 | } | ||
| 22453 | |||
| 22454 | /** Validate if passed-in "value" is a valid value for | ||
| 22455 | innodb_buffer_pool_filename. On Windows, file names with colon (:) | ||
| 22456 | are not allowed. | ||
| 22457 | @param[in] thd thread handle | ||
| 22458 | @param[in] save immediate result from update function | ||
| 22459 | @param[in] value incoming string | ||
| 22460 | @return 0 for valid name */ | ||
| 22461 | 9 | static int innodb_srv_buf_dump_filename_validate(THD *thd, SYS_VAR *, | |
| 22462 | void *save, | ||
| 22463 | struct st_mysql_value *value) { | ||
| 22464 | char buff[OS_FILE_MAX_PATH]; | ||
| 22465 | 9 | int len = sizeof(buff); | |
| 22466 | |||
| 22467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(save != nullptr); |
| 22468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(value != nullptr); |
| 22469 | |||
| 22470 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | const char *buf_name = value->val_str(value, buff, &len); |
| 22471 | |||
| 22472 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (buf_name == nullptr) { |
| 22473 | ✗ | return (1); | |
| 22474 | } | ||
| 22475 | |||
| 22476 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
|
9 | if (buf_name == buff) { |
| 22477 | /* Allocate from thd's memroot */ | ||
| 22478 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | buf_name = thd_strmake(thd, buf_name, len); |
| 22479 | } | ||
| 22480 | |||
| 22481 | #ifdef _WIN32 | ||
| 22482 | if (is_filename_allowed(buf_name, len, false)) { | ||
| 22483 | *static_cast<const char **>(save) = buf_name; | ||
| 22484 | return (0); | ||
| 22485 | } else { | ||
| 22486 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 22487 | "InnoDB: innodb_buffer_pool_filename" | ||
| 22488 | " cannot have colon (:) in the file name."); | ||
| 22489 | return (1); | ||
| 22490 | } | ||
| 22491 | #else /* _WIN32 */ | ||
| 22492 | 9 | *static_cast<const char **>(save) = buf_name; | |
| 22493 | 9 | return (0); | |
| 22494 | #endif | ||
| 22495 | } | ||
| 22496 | |||
| 22497 | #ifdef UNIV_DEBUG | ||
| 22498 | static char *srv_buffer_pool_evict; | ||
| 22499 | |||
| 22500 | /** Evict all uncompressed pages of compressed tables from the buffer pool. | ||
| 22501 | Keep the compressed pages in the buffer pool. | ||
| 22502 | @return whether all uncompressed pages were evicted */ | ||
| 22503 | 4 | [[nodiscard]] static bool innodb_buffer_pool_evict_uncompressed(void) { | |
| 22504 | 4 | bool all_evicted = true; | |
| 22505 | |||
| 22506 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for (ulint i = 0; i < srv_buf_pool_instances; i++) { |
| 22507 | 4 | buf_pool_t *buf_pool = &buf_pool_ptr[i]; | |
| 22508 | |||
| 22509 | 4 | mutex_enter(&buf_pool->LRU_list_mutex); | |
| 22510 | |||
| 22511 | 4 | for (buf_block_t *block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); | |
| 22512 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4 times.
|
19 | block != nullptr;) { |
| 22513 | 15 | buf_block_t *prev_block = UT_LIST_GET_PREV(unzip_LRU, block); | |
| 22514 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); |
| 22515 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | ut_ad(block->in_unzip_LRU_list); |
| 22516 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | ut_ad(block->page.in_LRU_list); |
| 22517 | |||
| 22518 | 15 | mutex_enter(&block->mutex); | |
| 22519 | |||
| 22520 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (!buf_LRU_free_page(&block->page, false)) { |
| 22521 | ✗ | mutex_exit(&block->mutex); | |
| 22522 | ✗ | all_evicted = false; | |
| 22523 | } else { | ||
| 22524 | /* buf_LRU_free_page() released LRU_list_mutex. | ||
| 22525 | have to restart the unzip_LRU scan. */ | ||
| 22526 | 15 | mutex_enter(&buf_pool->LRU_list_mutex); | |
| 22527 | 15 | block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); | |
| 22528 | 15 | continue; | |
| 22529 | } | ||
| 22530 | ✗ | block = prev_block; | |
| 22531 | } | ||
| 22532 | |||
| 22533 | 4 | mutex_exit(&buf_pool->LRU_list_mutex); | |
| 22534 | } | ||
| 22535 | |||
| 22536 | 4 | return (all_evicted); | |
| 22537 | } | ||
| 22538 | |||
| 22539 | /** Called on SET GLOBAL innodb_buffer_pool_evict=... | ||
| 22540 | Handles some values specially, to evict pages from the buffer pool. | ||
| 22541 | SET GLOBAL innodb_buffer_pool_evict='uncompressed' | ||
| 22542 | evicts all uncompressed page frames of compressed tablespaces. | ||
| 22543 | @param[in] save immediate result from check function */ | ||
| 22544 | 8 | static void innodb_buffer_pool_evict_update(THD *, SYS_VAR *, void *, | |
| 22545 | const void *save) { | ||
| 22546 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
|
8 | if (const char *op = *static_cast<const char *const *>(save)) { |
| 22547 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3 times.
|
7 | if (!strcmp(op, "uncompressed")) { |
| 22548 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | for (uint tries = 0; tries < 10000; tries++) { |
| 22549 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (innodb_buffer_pool_evict_uncompressed()) { |
| 22550 | 4 | return; | |
| 22551 | } | ||
| 22552 | |||
| 22553 | ✗ | std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
| 22554 | } | ||
| 22555 | |||
| 22556 | /* We failed to evict all uncompressed pages. */ | ||
| 22557 | ✗ | ut_d(ut_error); | |
| 22558 | } | ||
| 22559 | } | ||
| 22560 | } | ||
| 22561 | #endif /* UNIV_DEBUG */ | ||
| 22562 | |||
| 22563 | /** Update the system variable innodb_monitor_enable and enable | ||
| 22564 | specified monitor counter. | ||
| 22565 | This function is registered as a callback with MySQL. | ||
| 22566 | @param[in] thd thread handle | ||
| 22567 | @param[out] var_ptr where the formal string goes | ||
| 22568 | @param[in] save immediate result from check function */ | ||
| 22569 | 2496 | static void innodb_enable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 22570 | const void *save) { | ||
| 22571 | 2496 | innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON, true); | |
| 22572 | 2496 | } | |
| 22573 | |||
| 22574 | /** Update the system variable innodb_monitor_disable and turn | ||
| 22575 | off specified monitor counter. | ||
| 22576 | @param[in] thd thread handle | ||
| 22577 | @param[out] var_ptr where the formal string goes | ||
| 22578 | @param[in] save immediate result from check function */ | ||
| 22579 | 182 | static void innodb_disable_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 22580 | const void *save) { | ||
| 22581 | 182 | innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF, true); | |
| 22582 | 182 | } | |
| 22583 | |||
| 22584 | /** Update the system variable innodb_monitor_reset and reset | ||
| 22585 | specified monitor counter(s). | ||
| 22586 | This function is registered as a callback with MySQL. | ||
| 22587 | @param[in] thd thread handle | ||
| 22588 | @param[out] var_ptr where the formal string goes | ||
| 22589 | @param[in] save immediate result from check function */ | ||
| 22590 | 125 | static void innodb_reset_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 22591 | const void *save) { | ||
| 22592 | 125 | innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE, true); | |
| 22593 | 125 | } | |
| 22594 | |||
| 22595 | /** Update the system variable innodb_monitor_reset_all and reset | ||
| 22596 | all value related monitor counter. | ||
| 22597 | This function is registered as a callback with MySQL. | ||
| 22598 | @param[in] thd thread handle | ||
| 22599 | @param[out] var_ptr where the formal string goes | ||
| 22600 | @param[in] save immediate result from check function */ | ||
| 22601 | 93 | static void innodb_reset_all_monitor_update(THD *thd, SYS_VAR *, void *var_ptr, | |
| 22602 | const void *save) { | ||
| 22603 | 93 | innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE, true); | |
| 22604 | 93 | } | |
| 22605 | |||
| 22606 | /** Validate the value of innodb_undo_tablespaces global variable. This function | ||
| 22607 | is registered as a callback with MySQL. | ||
| 22608 | @param[in] thd thread handle | ||
| 22609 | @param[in] var pointer to system variable | ||
| 22610 | @param[in] var_ptr where the formal string goes | ||
| 22611 | @param[in] save immediate result from check function */ | ||
| 22612 | 6 | static void innodb_undo_tablespaces_update(THD *thd [[maybe_unused]], | |
| 22613 | SYS_VAR *var [[maybe_unused]], | ||
| 22614 | void *var_ptr [[maybe_unused]], | ||
| 22615 | const void *save [[maybe_unused]]) { | ||
| 22616 | 6 | innodb_undo_tablespaces_deprecate(); | |
| 22617 | 6 | } | |
| 22618 | |||
| 22619 | /** Validate the value of innodb_parallel_doublewrite_path global variable. | ||
| 22620 | This function is registered as a callback with MySQL. | ||
| 22621 | @param[in] thd thread handle | ||
| 22622 | @param[in] var pointer to system variable | ||
| 22623 | @param[in] var_ptr where the formal string goes | ||
| 22624 | @param[in] save immediate result from check function */ | ||
| 22625 | ✗ | static void innodb_parallel_doublewrite_path_update( | |
| 22626 | THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]], | ||
| 22627 | void *var_ptr [[maybe_unused]], | ||
| 22628 | const void *save [[maybe_unused]]) { | ||
| 22629 | ✗ | innodb_parallel_doublewrite_path_deprecate(); | |
| 22630 | } | ||
| 22631 | |||
| 22632 | /** Validate the value of innodb_parallel_dblwr_encrypt global variable. | ||
| 22633 | This function is registered as a callback with MySQL. | ||
| 22634 | @param[in] thd thread handle | ||
| 22635 | @param[in] var pointer to system variable | ||
| 22636 | @param[in] var_ptr where the formal string goes | ||
| 22637 | @param[in] save immediate result from check function */ | ||
| 22638 | 3 | static void innodb_parallel_dblwr_encrypt_update( | |
| 22639 | THD *thd [[maybe_unused]], SYS_VAR *var [[maybe_unused]], | ||
| 22640 | void *var_ptr [[maybe_unused]], | ||
| 22641 | const void *save [[maybe_unused]]) { | ||
| 22642 | 3 | innodb_parallel_dblwr_encrypt_deprecate(); | |
| 22643 | 3 | } | |
| 22644 | |||
| 22645 | /* Declare default check function for boolean system variable. Cannot include | ||
| 22646 | sql_plugin_var.h header in this file due to conflicting macro definitions. */ | ||
| 22647 | int check_func_bool(THD *, SYS_VAR *, void *save, st_mysql_value *value); | ||
| 22648 | |||
| 22649 | /** Validate the value of innodb_undo_log_encrypt global variable. This function | ||
| 22650 | is registered as a callback with MySQL. | ||
| 22651 | @param[in] thd thread handle | ||
| 22652 | @param[in] var pointer to system variable | ||
| 22653 | @param[in] save possibly updated variable value | ||
| 22654 | @param[in] value current variable value | ||
| 22655 | @return error code */ | ||
| 22656 | 86 | static int validate_innodb_undo_log_encrypt(THD *thd, SYS_VAR *var, void *save, | |
| 22657 | struct st_mysql_value *value) { | ||
| 22658 | /* Call the default check function first. */ | ||
| 22659 | 86 | auto error = check_func_bool(thd, var, save, value); | |
| 22660 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 83 times.
|
86 | if (error != 0) { |
| 22661 | 3 | return (error); | |
| 22662 | } | ||
| 22663 | 83 | bool target = *static_cast<bool *>(save); | |
| 22664 | |||
| 22665 | /* Set the default output to current value for all error cases. */ | ||
| 22666 | 83 | *static_cast<bool *>(save) = srv_undo_log_encrypt; | |
| 22667 | |||
| 22668 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 54 times.
|
83 | if (srv_undo_log_encrypt == target) { |
| 22669 | /* No change */ | ||
| 22670 | 29 | return (0); | |
| 22671 | } | ||
| 22672 | |||
| 22673 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 13 times.
|
54 | if (target) { |
| 22674 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (Encryption::is_online_encryption_on()) { |
| 22675 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22676 | "Undo log cannot be" | ||
| 22677 | " encrypted with Master Key encryption" | ||
| 22678 | " when online to KEYRING encryption is turned ON."); | ||
| 22679 | ✗ | return 1; | |
| 22680 | } | ||
| 22681 | } | ||
| 22682 | |||
| 22683 | /* If encryption is to be disabled. This will just make sure I/O doesn't | ||
| 22684 | write UNDO pages encrypted from now on. */ | ||
| 22685 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 41 times.
|
54 | if (target == false) { |
| 22686 | 13 | *static_cast<bool *>(save) = false; | |
| 22687 | 13 | return (0); | |
| 22688 | } | ||
| 22689 | |||
| 22690 | /* There would be at least 2 UNDO tablespaces */ | ||
| 22691 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | ut_ad(undo::spaces->size() >= FSP_IMPLICIT_UNDO_TABLESPACES); |
| 22692 | |||
| 22693 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 36 times.
|
41 | if (!Encryption::check_keyring()) { |
| 22694 | 5 | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_DA_UNDO_NO_KEYRING); | |
| 22695 | 5 | ib::error(ER_UNDO_NO_KEYRING); | |
| 22696 | 5 | return (0); | |
| 22697 | } | ||
| 22698 | |||
| 22699 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | if (srv_read_only_mode) { |
| 22700 | ✗ | ib::error(ER_IB_MSG_1051); | |
| 22701 | ✗ | ib_senderrf(thd, IB_LOG_LEVEL_WARN, ER_IB_MSG_1051); | |
| 22702 | ✗ | return (0); | |
| 22703 | } | ||
| 22704 | |||
| 22705 | /* UNDO tablespace encryption to be mutually exclusive with any UNDO DDL */ | ||
| 22706 | 36 | mutex_enter(&undo::ddl_mutex); | |
| 22707 | |||
| 22708 | /* Enable encryption for UNDO tablespaces */ | ||
| 22709 | 36 | bool ret = srv_enable_undo_encryption(nullptr); | |
| 22710 | |||
| 22711 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
|
36 | if (!ret) { |
| 22712 | /* At this point, all UNDO tablespaces have been encrypted. */ | ||
| 22713 | 34 | *static_cast<bool *>(save) = true; | |
| 22714 | } | ||
| 22715 | |||
| 22716 | 36 | mutex_exit(&undo::ddl_mutex); | |
| 22717 | 36 | return (0); | |
| 22718 | } | ||
| 22719 | |||
| 22720 | /** Validate the value of innodb_redo_log_encrypt global variable. This function | ||
| 22721 | is registered as a callback with MySQL. | ||
| 22722 | @param[in] thd thread handle | ||
| 22723 | @param[in] var pointer to system variable | ||
| 22724 | @param[in] save possibly updated variable value | ||
| 22725 | @param[in] value current variable value | ||
| 22726 | @return error code */ | ||
| 22727 | 90 | static int validate_innodb_redo_log_encrypt(THD *thd, SYS_VAR *var, void *save, | |
| 22728 | struct st_mysql_value *value) { | ||
| 22729 | /* Call the default check function first. */ | ||
| 22730 | 90 | auto error = check_func_bool(thd, var, save, value); | |
| 22731 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 87 times.
|
90 | if (error != 0) { |
| 22732 | 3 | return (error); | |
| 22733 | } | ||
| 22734 | 87 | bool target = *static_cast<bool *>(save); | |
| 22735 | |||
| 22736 | /* Set the default output to current value for all error cases. */ | ||
| 22737 | 87 | *static_cast<bool *>(save) = srv_redo_log_encrypt; | |
| 22738 | |||
| 22739 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 47 times.
|
87 | if (srv_redo_log_encrypt == target) { |
| 22740 | /* No change */ | ||
| 22741 | 40 | return (0); | |
| 22742 | } | ||
| 22743 | |||
| 22744 | /* If encryption is to be disabled. This will just make sure I/O doesn't | ||
| 22745 | write REDO encrypted from now on. */ | ||
| 22746 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 34 times.
|
47 | if (target == false) { |
| 22747 | 13 | *static_cast<bool *>(save) = false; | |
| 22748 | 13 | return (0); | |
| 22749 | } | ||
| 22750 | |||
| 22751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (srv_read_only_mode) { |
| 22752 | ✗ | ib::error(ER_IB_MSG_LOG_FILES_CANNOT_ENCRYPT_IN_READ_ONLY); | |
| 22753 | ✗ | return (0); | |
| 22754 | } | ||
| 22755 | |||
| 22756 | /* Enable encryption for REDO tablespaces */ | ||
| 22757 | 34 | bool ret = srv_enable_redo_encryption(); | |
| 22758 | |||
| 22759 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 7 times.
|
34 | if (!ret) { |
| 22760 | /* At this point, REDO log is set to be encrypted. */ | ||
| 22761 | 27 | *static_cast<bool *>(save) = true; | |
| 22762 | } | ||
| 22763 | 34 | return (0); | |
| 22764 | } | ||
| 22765 | |||
| 22766 | 9 | static int innodb_sys_tablespace_encyption_validate( | |
| 22767 | THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) { | ||
| 22768 | const char *innodb_sys_tablespace_encryption_input; | ||
| 22769 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 22770 | 9 | int len = sizeof(buff); | |
| 22771 | |||
| 22772 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(save != nullptr); |
| 22773 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | ut_a(value != nullptr); |
| 22774 | |||
| 22775 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | innodb_sys_tablespace_encryption_input = value->val_str(value, buff, &len); |
| 22776 | |||
| 22777 | 9 | bool legit_value = false; | |
| 22778 | 9 | uint use = 0; | |
| 22779 | // The last item of sys_tablespace_encrypt_names is nullptr | ||
| 22780 | 9 | const size_t encrypt_names_cnt = | |
| 22781 | array_elements(sys_tablespace_encrypt_names) - 1; | ||
| 22782 | |||
| 22783 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5 times.
|
27 | for (; use < encrypt_names_cnt; use++) { |
| 22784 |
3/4✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 18 times.
|
22 | if (!innobase_strcasecmp(innodb_sys_tablespace_encryption_input, |
| 22785 | sys_tablespace_encrypt_names[use])) { | ||
| 22786 | 4 | legit_value = true; | |
| 22787 | 4 | break; | |
| 22788 | } | ||
| 22789 | } | ||
| 22790 | // It is possible that enum value was provided as the integer, not literal | ||
| 22791 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
|
9 | if (!legit_value) { |
| 22792 | 5 | int error = 0; | |
| 22793 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | use = (uint)my_strtoll10(innodb_sys_tablespace_encryption_input, nullptr, |
| 22794 | &error); | ||
| 22795 |
4/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
|
5 | if (!error && use < encrypt_names_cnt) { |
| 22796 | 2 | legit_value = true; | |
| 22797 | } | ||
| 22798 | } | ||
| 22799 | |||
| 22800 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
|
9 | if (!legit_value) return 1; |
| 22801 | |||
| 22802 | 6 | const auto change_to_sys_tablespace_encryption = | |
| 22803 | static_cast<srv_sys_tablespace_encrypt_enum>(use); | ||
| 22804 | |||
| 22805 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_OFF) { |
| 22806 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_ON) { |
| 22807 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22808 | "System tablespace Master Key encryption cannot be " | ||
| 22809 | "turned OFF dynamically. " | ||
| 22810 | "However you can still re-encrypt system tablespace " | ||
| 22811 | "with encryption threads " | ||
| 22812 | "and then instruct encryption threads to decrypt the " | ||
| 22813 | "system tablespace."); | ||
| 22814 | ✗ | return 1; | |
| 22815 | } | ||
| 22816 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) { |
| 22817 | ✗ | push_warning_printf( | |
| 22818 | thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 22819 | "RE_ENCRYPTING_TO_KEYRING can be only used when system tablespace " | ||
| 22820 | "was previously encrypted with Master Key encryption. To encrypt " | ||
| 22821 | "system tablespace with KEYRING encryption please use encryption " | ||
| 22822 | "threads."); | ||
| 22823 | ✗ | return 1; | |
| 22824 | } | ||
| 22825 | } | ||
| 22826 | |||
| 22827 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | if (change_to_sys_tablespace_encryption == SYS_TABLESPACE_ENCRYPT_ON) { |
| 22828 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) { |
| 22829 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | push_warning_printf( |
| 22830 | thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 22831 | "System tablespace Master Key encryption can be turned ON only " | ||
| 22832 | "at bootstrap. You can still encrypt System tablespace encryption " | ||
| 22833 | "with " | ||
| 22834 | "KEYRING encryption."); | ||
| 22835 | 2 | return 1; | |
| 22836 | ✗ | } else if (srv_sys_tablespace_encrypt == | |
| 22837 | SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING) { | ||
| 22838 | // The system tablespace encryption was marked to be re-encrypted to | ||
| 22839 | // keyring. We allow it to be set back to ON in case encryption threads | ||
| 22840 | // were not yet activated and system tablespace remain encrypted with | ||
| 22841 | // Master Key. | ||
| 22842 | ✗ | if (Encryption::is_online_encryption_on()) { | |
| 22843 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22844 | "System tablespace cannot be marked as encrypted " | ||
| 22845 | "with Master Key encryption " | ||
| 22846 | "when Online to keyring encryption is turned ON or " | ||
| 22847 | "when system tablespace " | ||
| 22848 | "was already encrypted with KEYRING encryption."); | ||
| 22849 | ✗ | return 1; | |
| 22850 | } else { | ||
| 22851 | ✗ | fil_space_t *space = fil_space_acquire_silent(TRX_SYS_SPACE); | |
| 22852 | ✗ | ut_ad(space != nullptr); | |
| 22853 | ✗ | fil_space_crypt_t *crypt_data = space->crypt_data; | |
| 22854 | ✗ | fil_space_release(space); | |
| 22855 | |||
| 22856 | ✗ | if (crypt_data != nullptr) { | |
| 22857 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, | |
| 22858 | ER_WRONG_ARGUMENTS, | ||
| 22859 | "System tablespace cannot be marked as encrypted " | ||
| 22860 | "with Master Key encryption " | ||
| 22861 | "as it was already encrypted with KEYRING " | ||
| 22862 | "encryption and Master Key encryption " | ||
| 22863 | "is bootstrap only option."); | ||
| 22864 | ✗ | return 1; | |
| 22865 | } | ||
| 22866 | } | ||
| 22867 | } | ||
| 22868 | } | ||
| 22869 | |||
| 22870 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (change_to_sys_tablespace_encryption == |
| 22871 | 1 | SYS_TABLESPACE_RE_ENCRYPTING_TO_KEYRING && | |
| 22872 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | srv_sys_tablespace_encrypt == SYS_TABLESPACE_ENCRYPT_OFF) { |
| 22873 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | push_warning_printf( |
| 22874 | thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | ||
| 22875 | "System tablespace can only be marked to be re-encrypted with keyring " | ||
| 22876 | "in " | ||
| 22877 | "case it was previosly encrypted with Master Key encryption. " | ||
| 22878 | "You still can encrypt unencrypted system tablespace with encryption " | ||
| 22879 | "threads."); | ||
| 22880 | 1 | return 1; | |
| 22881 | } | ||
| 22882 | |||
| 22883 | 3 | *static_cast<ulong *>(save) = use; | |
| 22884 | |||
| 22885 | 3 | return 0; | |
| 22886 | } | ||
| 22887 | |||
| 22888 | /** Update the number of rollback segments per tablespace when the | ||
| 22889 | system variable innodb_rollback_segments is changed. | ||
| 22890 | This function is registered as a callback with MySQL. | ||
| 22891 | @param[in] save immediate result from check function */ | ||
| 22892 | 22 | static void innodb_rollback_segments_update(THD *, SYS_VAR *, void *, | |
| 22893 | const void *save) { | ||
| 22894 | 22 | ulong target = *static_cast<const ulong *>(save); | |
| 22895 | |||
| 22896 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 15 times.
|
22 | if (srv_rollback_segments == target) { |
| 22897 | 11 | return; | |
| 22898 | } | ||
| 22899 | |||
| 22900 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
|
15 | if (srv_read_only_mode) { |
| 22901 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | ib::warn(ER_IB_MSG_578) << "Cannot set innodb_rollback_segments to " |
| 22902 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | << target << " when in read-only mode"; |
| 22903 | 2 | return; | |
| 22904 | } | ||
| 22905 | |||
| 22906 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
|
13 | if (srv_force_recovery > 0) { |
| 22907 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | ib::warn(ER_IB_MSG_579) << "Cannot set innodb_rollback_segments to " |
| 22908 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | << target << " when in innodb_force_recovery > 0"; |
| 22909 | 2 | return; | |
| 22910 | } | ||
| 22911 | |||
| 22912 | /* Serialize this adjustment with all undo tablespace DDLs. */ | ||
| 22913 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | mutex_enter(&undo::ddl_mutex); |
| 22914 | |||
| 22915 |
2/4✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
|
11 | if (!trx_rseg_adjust_rollback_segments(target)) { |
| 22916 | ✗ | ib::warn(ER_IB_MSG_580) | |
| 22917 | ✗ | << "Failed to set innodb_rollback_segments to " << target; | |
| 22918 | ✗ | return; | |
| 22919 | } | ||
| 22920 | |||
| 22921 | 11 | srv_rollback_segments = target; | |
| 22922 | |||
| 22923 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | mutex_exit(&undo::ddl_mutex); |
| 22924 | } | ||
| 22925 | |||
| 22926 | /** Parse and enable InnoDB monitor counters during server startup. | ||
| 22927 | User can list the monitor counters/groups to be enable by specifying | ||
| 22928 | "loose-innodb_monitor_enable=monitor_name1;monitor_name2..." | ||
| 22929 | in server configuration file or at the command line. The string | ||
| 22930 | separate could be ";", "," or empty space. */ | ||
| 22931 | 2 | static void innodb_enable_monitor_at_startup( | |
| 22932 | char *str) /*!< in/out: monitor counter enable list */ | ||
| 22933 | { | ||
| 22934 | static const char *sep = " ;,"; | ||
| 22935 | char *last; | ||
| 22936 | |||
| 22937 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | ut_a(str); |
| 22938 | |||
| 22939 | /* Walk through the string, and separate each monitor counter | ||
| 22940 | and/or counter group name, and calling innodb_monitor_update() | ||
| 22941 | if successfully updated. Please note that the "str" would be | ||
| 22942 | changed by strtok_r() as it walks through it. */ | ||
| 22943 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | for (char *option = my_strtok_r(str, sep, &last); option; |
| 22944 | 2 | option = my_strtok_r(nullptr, sep, &last)) { | |
| 22945 | ulint ret; | ||
| 22946 | char *option_name; | ||
| 22947 | |||
| 22948 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | ret = innodb_monitor_valid_byname(&option_name, option); |
| 22949 | |||
| 22950 | /* The name is validated if ret == 0 */ | ||
| 22951 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (!ret) { |
| 22952 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | innodb_monitor_update(nullptr, nullptr, &option, MONITOR_TURN_ON, false); |
| 22953 | } else { | ||
| 22954 | ✗ | log_errlog(WARNING_LEVEL, ER_INNODB_INVALID_MONITOR_COUNTER_NAME, option); | |
| 22955 | } | ||
| 22956 | } | ||
| 22957 | 2 | } | |
| 22958 | |||
| 22959 | #if defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || defined(UNIV_PERF_DEBUG)) | ||
| 22960 | |||
| 22961 | /** Update the innodb_sched_priority_purge variable and set the thread | ||
| 22962 | priorities accordingly. | ||
| 22963 | @param[in] thd thread handle | ||
| 22964 | @param[in] var pointer to system variable | ||
| 22965 | @param[out] var_ptr where the formal string goes | ||
| 22966 | @param[in] save immediate result from check function */ | ||
| 22967 | 8 | static void innodb_sched_priority_purge_update(THD *thd, SYS_VAR *var, | |
| 22968 | void *var_ptr, | ||
| 22969 | const void *save) { | ||
| 22970 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (srv_read_only_mode) return; |
| 22971 | |||
| 22972 | 8 | const ulint priority = *static_cast<const ulint *>(save); | |
| 22973 | |||
| 22974 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
|
40 | for (ulint i = 0; i < srv_n_purge_threads; i++) { |
| 22975 | const ulint actual_priority = | ||
| 22976 | 32 | os_thread_set_priority(srv_purge_tids[i], priority); | |
| 22977 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (UNIV_UNLIKELY(actual_priority != priority)) { |
| 22978 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 22979 | "Failed to set the purge thread priority to %lu, " | ||
| 22980 | "the current priority is %lu, aborting priority " | ||
| 22981 | "update", | ||
| 22982 | priority, actual_priority); | ||
| 22983 | ✗ | return; | |
| 22984 | } | ||
| 22985 | } | ||
| 22986 | |||
| 22987 | 8 | srv_sched_priority_purge = priority; | |
| 22988 | } | ||
| 22989 | |||
| 22990 | /** Update the innodb_sched_priority_io variable and set the thread priorities | ||
| 22991 | accordingly. | ||
| 22992 | @param[in] thd thread handle | ||
| 22993 | @param[in] var pointer to system variable | ||
| 22994 | @param[out] var_ptr where the formal string goes | ||
| 22995 | @param[in] save immediate result from check function */ | ||
| 22996 | 7 | static void innodb_sched_priority_io_update(THD *thd, SYS_VAR *var, | |
| 22997 | void *var_ptr, const void *save) { | ||
| 22998 | 7 | const ulint priority = *static_cast<const ulint *>(save); | |
| 22999 | |||
| 23000 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 7 times.
|
77 | for (ulint i = 0; i < srv_n_file_io_threads; i++) { |
| 23001 | const ulint actual_priority = | ||
| 23002 | 70 | os_thread_set_priority(srv_io_tids[i], priority); | |
| 23003 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
|
70 | if (UNIV_UNLIKELY(actual_priority != priority)) { |
| 23004 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23005 | "Failed to set the I/O thread priority to %lu, the " | ||
| 23006 | "current priority is %lu, aborting priority update", | ||
| 23007 | priority, actual_priority); | ||
| 23008 | ✗ | return; | |
| 23009 | } | ||
| 23010 | } | ||
| 23011 | 7 | srv_sched_priority_io = priority; | |
| 23012 | } | ||
| 23013 | |||
| 23014 | /** Update the innodb_sched_priority_master variable and set the thread | ||
| 23015 | priorities accordingly. | ||
| 23016 | @param[in] thd thread handle | ||
| 23017 | @param[in] var pointer to system variable | ||
| 23018 | @param[out] var_ptr where the formal string goes | ||
| 23019 | @param[in] save immediate result from check function */ | ||
| 23020 | 7 | static void innodb_sched_priority_master_update(THD *thd, SYS_VAR *var, | |
| 23021 | void *var_ptr, | ||
| 23022 | const void *save) { | ||
| 23023 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (srv_read_only_mode) return; |
| 23024 | |||
| 23025 | 7 | const ulint priority = *static_cast<const lint *>(save); | |
| 23026 | const ulint actual_priority = | ||
| 23027 | 7 | os_thread_set_priority(srv_master_tid, priority); | |
| 23028 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (UNIV_UNLIKELY(actual_priority != priority)) { |
| 23029 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23030 | "Failed to set the master thread priority to %lu, the " | ||
| 23031 | "current priority is %lu", | ||
| 23032 | priority, actual_priority); | ||
| 23033 | } else { | ||
| 23034 | 7 | srv_sched_priority_master = priority; | |
| 23035 | } | ||
| 23036 | } | ||
| 23037 | |||
| 23038 | #endif /* defined(UNIV_LINUX) && (defined(UNIV_DEBUG) || \ | ||
| 23039 | defined(UNIV_PERF_DEBUG)) */ | ||
| 23040 | |||
| 23041 | /** Callback function for accessing the InnoDB variables from MySQL: | ||
| 23042 | SHOW VARIABLES. */ | ||
| 23043 | 107956 | static int show_innodb_vars(THD *, SHOW_VAR *var, char *) { | |
| 23044 | 107956 | innodb_export_status(); | |
| 23045 | 107953 | var->type = SHOW_ARRAY; | |
| 23046 | 107953 | var->value = (char *)&innodb_status_variables; | |
| 23047 | 107953 | var->scope = SHOW_SCOPE_GLOBAL; | |
| 23048 | |||
| 23049 | 107953 | return (0); | |
| 23050 | } | ||
| 23051 | |||
| 23052 | /** This function checks each index name for a table against reserved | ||
| 23053 | system default primary index name 'GEN_CLUST_INDEX'. If a name | ||
| 23054 | matches, this function pushes an warning message to the client, | ||
| 23055 | and returns true. | ||
| 23056 | @return true if the index name matches the reserved name */ | ||
| 23057 | 458569 | bool innobase_index_name_is_reserved( | |
| 23058 | THD *thd, /*!< in/out: MySQL connection */ | ||
| 23059 | const KEY *key_info, /*!< in: Indexes to be created */ | ||
| 23060 | ulint num_of_keys) /*!< in: Number of indexes to | ||
| 23061 | be created. */ | ||
| 23062 | { | ||
| 23063 | const KEY *key; | ||
| 23064 | uint key_num; /* index number */ | ||
| 23065 | |||
| 23066 |
2/2✓ Branch 0 taken 231907 times.
✓ Branch 1 taken 458566 times.
|
690473 | for (key_num = 0; key_num < num_of_keys; key_num++) { |
| 23067 | 231907 | key = &key_info[key_num]; | |
| 23068 | |||
| 23069 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 231904 times.
|
231907 | if (innobase_strcasecmp(key->name, innobase_index_reserve_name) == 0) { |
| 23070 | /* Push warning to mysql */ | ||
| 23071 | 3 | push_warning_printf(thd, Sql_condition::SL_WARNING, | |
| 23072 | ER_WRONG_NAME_FOR_INDEX, | ||
| 23073 | "Cannot Create Index with name" | ||
| 23074 | " '%s'. The name is reserved" | ||
| 23075 | " for the system default primary" | ||
| 23076 | " index.", | ||
| 23077 | innobase_index_reserve_name); | ||
| 23078 | |||
| 23079 | 3 | my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), innobase_index_reserve_name); | |
| 23080 | |||
| 23081 | 3 | return (true); | |
| 23082 | } | ||
| 23083 | } | ||
| 23084 | |||
| 23085 | 458566 | return (false); | |
| 23086 | } | ||
| 23087 | |||
| 23088 | /** Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 23089 | of m_prebuilt->fts_doc_id | ||
| 23090 | @param[in,out] fts_hdl FTS handler | ||
| 23091 | @return the relevance ranking value */ | ||
| 23092 | 2962 | static float innobase_fts_retrieve_ranking(FT_INFO *fts_hdl) { | |
| 23093 | fts_result_t *result; | ||
| 23094 | row_prebuilt_t *ft_prebuilt [[maybe_unused]]; | ||
| 23095 | |||
| 23096 | 2962 | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 23097 | |||
| 23098 | 2962 | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt; | |
| 23099 | |||
| 23100 | 2962 | fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 23101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2962 times.
|
2962 | assert(ft_prebuilt->fts_doc_id == ranking->doc_id); |
| 23102 | |||
| 23103 | 2962 | return (ranking->rank); | |
| 23104 | } | ||
| 23105 | |||
| 23106 | /** Free the memory for the FTS handler | ||
| 23107 | @param[in,out] fts_hdl FTS handler */ | ||
| 23108 | 2283 | static void innobase_fts_close_ranking(FT_INFO *fts_hdl) { | |
| 23109 | fts_result_t *result; | ||
| 23110 | |||
| 23111 | 2283 | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 23112 | |||
| 23113 | 2283 | fts_query_free_result(result); | |
| 23114 | |||
| 23115 | 2283 | my_free((uchar *)fts_hdl); | |
| 23116 | 2283 | } | |
| 23117 | |||
| 23118 | /** Find and Retrieve the FTS Relevance Ranking result for doc with doc_id | ||
| 23119 | of m_prebuilt->fts_doc_id | ||
| 23120 | @param[in,out] fts_hdl FTS handler | ||
| 23121 | @return the relevance ranking value */ | ||
| 23122 | 5656 | static float innobase_fts_find_ranking(FT_INFO *fts_hdl, uchar *, uint) { | |
| 23123 | fts_result_t *result; | ||
| 23124 | row_prebuilt_t *ft_prebuilt; | ||
| 23125 | |||
| 23126 | 5656 | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt; | |
| 23127 | 5656 | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 23128 | |||
| 23129 | /* Retrieve the ranking value for doc_id with value of | ||
| 23130 | m_prebuilt->fts_doc_id */ | ||
| 23131 | 5656 | return (fts_retrieve_ranking(result, ft_prebuilt->fts_doc_id)); | |
| 23132 | } | ||
| 23133 | |||
| 23134 | #ifdef UNIV_DEBUG | ||
| 23135 | static bool innodb_background_drop_list_empty = true; | ||
| 23136 | static bool innodb_purge_run_now = true; | ||
| 23137 | static bool innodb_purge_stop_now = true; | ||
| 23138 | static bool innodb_log_checkpoint_now = true; | ||
| 23139 | static bool innodb_log_checkpoint_fuzzy_now = true; | ||
| 23140 | static bool innodb_log_flush_now = true; | ||
| 23141 | static bool innodb_buf_flush_list_now = true; | ||
| 23142 | |||
| 23143 | static uint innodb_merge_threshold_set_all_debug = | ||
| 23144 | DICT_INDEX_MERGE_THRESHOLD_DEFAULT; | ||
| 23145 | |||
| 23146 | /** Wait for the background drop list to become empty. */ | ||
| 23147 | 4 | static void wait_background_drop_list_empty(THD *, SYS_VAR *, void *, | |
| 23148 | const void *) { | ||
| 23149 | 4 | row_wait_for_background_drop_list_empty(); | |
| 23150 | 4 | } | |
| 23151 | |||
| 23152 | /** Set the purge state to RUN. If purge is disabled then it | ||
| 23153 | is a no-op. This function is registered as a callback with MySQL. | ||
| 23154 | @param[in] save immediate result from check function */ | ||
| 23155 | 464 | static void purge_run_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 23156 |
5/6✓ Branch 0 taken 461 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 461 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 461 times.
✓ Branch 5 taken 3 times.
|
464 | if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) { |
| 23157 | 461 | trx_purge_run(); | |
| 23158 | } | ||
| 23159 | 464 | } | |
| 23160 | |||
| 23161 | /** Set the purge state to STOP. If purge is disabled then it | ||
| 23162 | is a no-op. This function is registered as a callback with MySQL. | ||
| 23163 | @param[in] save immediate result from check function */ | ||
| 23164 | 102 | static void purge_stop_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 23165 |
5/6✓ Branch 0 taken 97 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 97 times.
✓ Branch 5 taken 5 times.
|
102 | if (*(bool *)save && trx_purge_state() != PURGE_STATE_DISABLED) { |
| 23166 | 97 | trx_purge_stop(); | |
| 23167 | } | ||
| 23168 | 102 | } | |
| 23169 | |||
| 23170 | /** Force InnoDB to flush redo log up to current_lsn. | ||
| 23171 | This function is registered as a callback with MySQL. | ||
| 23172 | @param[in] save immediate result from check function */ | ||
| 23173 | 8 | static void log_flush_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 23174 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | if (!*(bool *)save) { |
| 23175 | 6 | return; | |
| 23176 | } | ||
| 23177 | |||
| 23178 | 2 | log_buffer_flush_to_disk(true); | |
| 23179 | } | ||
| 23180 | |||
| 23181 | /** Force InnoDB to do sharp checkpoint. This forces a flush of all | ||
| 23182 | dirty pages. | ||
| 23183 | @param[in] save immediate result from check function */ | ||
| 23184 | 31 | static void checkpoint_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 23185 |
3/4✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
31 | if (*(bool *)save && !srv_checkpoint_disabled) { |
| 23186 | /* Note that it's defined only when UNIV_DEBUG is defined. | ||
| 23187 | It seems to be very risky feature. Fortunately it is used | ||
| 23188 | only inside mtr tests. */ | ||
| 23189 | |||
| 23190 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 24 times.
|
73 | while (log_make_latest_checkpoint(*log_sys)) { |
| 23191 | /* Creating checkpoint could itself result in | ||
| 23192 | new log records. Hence we repeat until: | ||
| 23193 | last_checkpoint_lsn = log_get_lsn(). */ | ||
| 23194 | } | ||
| 23195 | |||
| 23196 | 48 | dberr_t err = fil_write_flushed_lsn(log_sys->last_checkpoint_lsn.load()); | |
| 23197 | |||
| 23198 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | ut_a(err == DB_SUCCESS); |
| 23199 | } | ||
| 23200 | 31 | } | |
| 23201 | |||
| 23202 | /** Force InnoDB to do fuzzy checkpoint. Fuzzy checkpoint does not | ||
| 23203 | force InnoDB to flush dirty pages. It only forces to write the new | ||
| 23204 | checkpoint_lsn to the header of the log file containing that LSN. | ||
| 23205 | This LSN is where the recovery starts. You can read more about the | ||
| 23206 | fuzzy checkpoints in the internet. | ||
| 23207 | @param[in] save immediate result from check function */ | ||
| 23208 | 8 | static void checkpoint_fuzzy_now_set(THD *, SYS_VAR *, void *, | |
| 23209 | const void *save) { | ||
| 23210 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
8 | if (*(bool *)save && !srv_checkpoint_disabled) { |
| 23211 | /* Note that it's defined only when UNIV_DEBUG is defined. | ||
| 23212 | It seems to be very risky feature. Fortunately it is used | ||
| 23213 | only inside mtr tests. */ | ||
| 23214 | |||
| 23215 | 2 | log_request_checkpoint(*log_sys, true); | |
| 23216 | } | ||
| 23217 | 8 | } | |
| 23218 | |||
| 23219 | /** Updates srv_checkpoint_disabled - allowing or disallowing checkpoints. | ||
| 23220 | This is called when user invokes SET GLOBAL innodb_checkpoints_disabled=0/1. | ||
| 23221 | After checkpoints are disabled, there will be no write of a checkpoint, | ||
| 23222 | until checkpoints are re-enabled (log_sys->checkpointer_mutex protects that) | ||
| 23223 | @param[in] save immediate result from check function */ | ||
| 23224 | 94 | static void checkpoint_disabled_update(THD *, SYS_VAR *, void *, | |
| 23225 | const void *save) { | ||
| 23226 | /* We need to acquire the checkpointer_mutex, to ensure that | ||
| 23227 | after we have finished this function, there will be no new | ||
| 23228 | checkpoint written (e.g. in case there is currently curring | ||
| 23229 | checkpoint). When checkpoint is being written, the same mutex | ||
| 23230 | is acquired, current value of srv_checkpoint_disabled is checked, | ||
| 23231 | and if checkpoints are disabled, we cancel writing the checkpoint. */ | ||
| 23232 | |||
| 23233 | 94 | log_t &log = *log_sys; | |
| 23234 | |||
| 23235 | 94 | log_checkpointer_mutex_enter(log); | |
| 23236 | 94 | log_limits_mutex_enter(log); | |
| 23237 | |||
| 23238 | 94 | srv_checkpoint_disabled = *static_cast<const bool *>(save); | |
| 23239 | |||
| 23240 | 94 | log_limits_mutex_exit(log); | |
| 23241 | 94 | log_checkpointer_mutex_exit(log); | |
| 23242 | 94 | } | |
| 23243 | |||
| 23244 | /** Force a dirty pages flush now. | ||
| 23245 | @param[in] save immediate result from check function */ | ||
| 23246 | 218 | static void buf_flush_list_now_set(THD *, SYS_VAR *, void *, const void *save) { | |
| 23247 |
2/2✓ Branch 0 taken 213 times.
✓ Branch 1 taken 5 times.
|
218 | if (*(bool *)save) { |
| 23248 | 213 | buf_flush_sync_all_buf_pools(); | |
| 23249 | } | ||
| 23250 | 218 | } | |
| 23251 | |||
| 23252 | /** Override current MERGE_THRESHOLD setting for all indexes at dictionary | ||
| 23253 | now. | ||
| 23254 | @param[in] save immediate result from check function */ | ||
| 23255 | 7 | static void innodb_merge_threshold_set_all_debug_update(THD *, SYS_VAR *, | |
| 23256 | void *, | ||
| 23257 | const void *save) { | ||
| 23258 | 7 | innodb_merge_threshold_set_all_debug = (*static_cast<const uint *>(save)); | |
| 23259 | 7 | dict_set_merge_threshold_all_debug(innodb_merge_threshold_set_all_debug); | |
| 23260 | 7 | } | |
| 23261 | |||
| 23262 | #endif /* UNIV_DEBUG */ | ||
| 23263 | |||
| 23264 | /** Find and Retrieve the FTS doc_id for the current result row | ||
| 23265 | @param[in,out] fts_hdl FTS handler | ||
| 23266 | @return the document ID */ | ||
| 23267 | ✗ | static ulonglong innobase_fts_retrieve_docid(FT_INFO_EXT *fts_hdl) { | |
| 23268 | fts_result_t *result; | ||
| 23269 | row_prebuilt_t *ft_prebuilt; | ||
| 23270 | |||
| 23271 | ✗ | ft_prebuilt = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_prebuilt; | |
| 23272 | ✗ | result = reinterpret_cast<NEW_FT_INFO *>(fts_hdl)->ft_result; | |
| 23273 | |||
| 23274 | ✗ | if (ft_prebuilt->read_just_key) { | |
| 23275 | ✗ | fts_ranking_t *ranking = rbt_value(fts_ranking_t, result->current); | |
| 23276 | |||
| 23277 | ✗ | return (ranking->doc_id); | |
| 23278 | } | ||
| 23279 | |||
| 23280 | ✗ | return (ft_prebuilt->fts_doc_id); | |
| 23281 | } | ||
| 23282 | |||
| 23283 | /* These variables are never read by InnoDB or changed. They are a kind of | ||
| 23284 | dummies that are needed by the MySQL infrastructure to call | ||
| 23285 | buffer_pool_dump_now(), buffer_pool_load_now() and buffer_pool_load_abort() | ||
| 23286 | by the user by doing: | ||
| 23287 | SET GLOBAL innodb_buffer_pool_dump_now=ON; | ||
| 23288 | SET GLOBAL innodb_buffer_pool_load_now=ON; | ||
| 23289 | SET GLOBAL innodb_buffer_pool_load_abort=ON; | ||
| 23290 | Their values are read by MySQL and displayed to the user when the variables | ||
| 23291 | are queried, e.g.: | ||
| 23292 | SELECT @@innodb_buffer_pool_dump_now; | ||
| 23293 | SELECT @@innodb_buffer_pool_load_now; | ||
| 23294 | SELECT @@innodb_buffer_pool_load_abort; */ | ||
| 23295 | static bool innodb_buffer_pool_dump_now = false; | ||
| 23296 | static bool innodb_buffer_pool_load_now = false; | ||
| 23297 | static bool innodb_buffer_pool_load_abort = false; | ||
| 23298 | |||
| 23299 | /** Trigger a dump of the buffer pool if innodb_buffer_pool_dump_now is set | ||
| 23300 | to ON. This function is registered as a callback with MySQL. | ||
| 23301 | @param[in] save immediate result from check function */ | ||
| 23302 | 10 | static void buffer_pool_dump_now(THD *, SYS_VAR *, void *, const void *save) { | |
| 23303 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
10 | if (*(bool *)save && !srv_read_only_mode) { |
| 23304 | 7 | buf_dump_start(); | |
| 23305 | } | ||
| 23306 | 10 | } | |
| 23307 | |||
| 23308 | /** Trigger a load of the buffer pool if innodb_buffer_pool_load_now is set | ||
| 23309 | to ON. This function is registered as a callback with MySQL. | ||
| 23310 | @param[in] save immediate result from check function */ | ||
| 23311 | 9 | static void buffer_pool_load_now(THD *, SYS_VAR *, void *, const void *save) { | |
| 23312 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | if (*(bool *)save) { |
| 23313 | 6 | buf_load_start(); | |
| 23314 | } | ||
| 23315 | 9 | } | |
| 23316 | |||
| 23317 | /** Abort a load of the buffer pool if innodb_buffer_pool_load_abort | ||
| 23318 | is set to ON. This function is registered as a callback with MySQL. | ||
| 23319 | @param[in] save immediate result from check function */ | ||
| 23320 | 4 | static void buffer_pool_load_abort(THD *, SYS_VAR *, void *, const void *save) { | |
| 23321 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (*(bool *)save) { |
| 23322 | 1 | buf_load_abort(); | |
| 23323 | } | ||
| 23324 | 4 | } | |
| 23325 | |||
| 23326 | /** Update the system variable innodb_log_write_ahead_size using the "saved" | ||
| 23327 | value. This function is registered as a callback with MySQL. | ||
| 23328 | @param[in] thd thread handle | ||
| 23329 | @param[in] save immediate result from check function */ | ||
| 23330 | 163 | static void innodb_log_write_ahead_size_update(THD *thd, SYS_VAR *, void *, | |
| 23331 | const void *save) { | ||
| 23332 | 163 | ulong val = INNODB_LOG_WRITE_AHEAD_SIZE_MIN; | |
| 23333 | 163 | ulong in_val = *static_cast<const ulong *>(save); | |
| 23334 | |||
| 23335 |
2/2✓ Branch 0 taken 412 times.
✓ Branch 1 taken 163 times.
|
575 | while (val < in_val) { |
| 23336 | 412 | val = val * 2; | |
| 23337 | } | ||
| 23338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
|
163 | if (val > INNODB_LOG_WRITE_AHEAD_SIZE_MAX) { |
| 23339 | ✗ | val = INNODB_LOG_WRITE_AHEAD_SIZE_MAX; | |
| 23340 | } | ||
| 23341 | |||
| 23342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163 times.
|
163 | if (val > UNIV_PAGE_SIZE) { |
| 23343 | ✗ | val = UNIV_PAGE_SIZE; | |
| 23344 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23345 | "innodb_log_write_ahead_size cannot" | ||
| 23346 | " be set higher than innodb_page_size."); | ||
| 23347 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
|
163 | } else if (val != in_val) { |
| 23348 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23349 | "innodb_log_write_ahead_size should be" | ||
| 23350 | " set to power of 2, in range [%lu,%lu]", | ||
| 23351 | INNODB_LOG_WRITE_AHEAD_SIZE_MIN, | ||
| 23352 | INNODB_LOG_WRITE_AHEAD_SIZE_MAX); | ||
| 23353 | } | ||
| 23354 | |||
| 23355 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 162 times.
|
163 | if (val != in_val) { |
| 23356 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23357 | "Setting innodb_log_write_ahead_size" | ||
| 23358 | " to %lu", | ||
| 23359 | val); | ||
| 23360 | } | ||
| 23361 | |||
| 23362 | 163 | log_write_ahead_resize(*log_sys, val); | |
| 23363 | 163 | } | |
| 23364 | |||
| 23365 | /** Update the system variable innodb_log_buffer_size using the "saved" | ||
| 23366 | value. This function is registered as a callback with MySQL. | ||
| 23367 | @param[in] save immediate result from check function */ | ||
| 23368 | 165 | static void innodb_log_buffer_size_update(THD *, SYS_VAR *, void *, | |
| 23369 | const void *save) { | ||
| 23370 | 165 | const ulong val = *static_cast<const ulong *>(save); | |
| 23371 | |||
| 23372 |
3/6✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 5 not taken.
|
165 | ib::info(ER_IB_MSG_1255) << "Setting innodb_log_buffer_size to " << val; |
| 23373 | |||
| 23374 |
2/4✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 165 times.
|
165 | if (!log_buffer_resize(*log_sys, val)) { |
| 23375 | /* This could happen if we tried to decrease size of the | ||
| 23376 | log buffer but we had more data in the log buffer than | ||
| 23377 | the new size. We could have asked for writing the data to | ||
| 23378 | disk, after x-locking the log buffer, but this could lead | ||
| 23379 | to deadlock if there was no space in log files and checkpoint | ||
| 23380 | was required (because checkpoint writes new redo records | ||
| 23381 | when persisting dd table buffer). That's why we don't ask | ||
| 23382 | for writing to disk. */ | ||
| 23383 | |||
| 23384 | ✗ | ib::error(ER_IB_MSG_1256) << "Failed to change size of the log buffer." | |
| 23385 | ✗ | " Try flushing the log buffer first."; | |
| 23386 | } | ||
| 23387 | 165 | } | |
| 23388 | |||
| 23389 | /** Update the innodb_log_writer_threads parameter. | ||
| 23390 | @param[out] var_ptr current value | ||
| 23391 | @param[in] save immediate result from check function */ | ||
| 23392 | 6 | static void innodb_log_writer_threads_update(THD *, SYS_VAR *, void *var_ptr, | |
| 23393 | const void *save) { | ||
| 23394 | 6 | *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 23395 | |||
| 23396 | /* pause/resume the log writer threads based on innodb_log_writer_threads | ||
| 23397 | value. */ | ||
| 23398 | 6 | log_control_writer_threads(*log_sys); | |
| 23399 | 6 | } | |
| 23400 | |||
| 23401 | /** Update the system variable innodb_redo_log_capacity using the "saved" | ||
| 23402 | value. This function is registered as a callback with MySQL. | ||
| 23403 | @param[in] thd thread handle | ||
| 23404 | @param[in] save immediate result from check function */ | ||
| 23405 | 10 | static void innodb_redo_log_capacity_update(THD *thd, SYS_VAR *, void *, | |
| 23406 | const void *save) { | ||
| 23407 | 10 | const auto new_value = *static_cast<const ulonglong *>(save); | |
| 23408 | |||
| 23409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | ut_a(LOG_CAPACITY_MIN <= new_value); |
| 23410 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | ut_a(new_value <= LOG_CAPACITY_MAX); |
| 23411 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | ut_a(new_value % MB == 0); |
| 23412 | |||
| 23413 | 10 | srv_redo_log_capacity = new_value; | |
| 23414 | |||
| 23415 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
|
10 | if (new_value == srv_redo_log_capacity_used) { |
| 23416 | 4 | return; | |
| 23417 | } | ||
| 23418 | |||
| 23419 | 6 | srv_redo_log_capacity_used = new_value; | |
| 23420 | |||
| 23421 | 6 | ib::info(ER_IB_MSG_LOG_FILES_CAPACITY_CHANGED, | |
| 23422 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | srv_redo_log_capacity_used / MB); |
| 23423 | |||
| 23424 | 6 | log_files_resize_requested(*log_sys); | |
| 23425 | |||
| 23426 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!log_sys->concurrency_margin_is_safe.load()) { |
| 23427 | ✗ | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23428 | "Current innodb_redo_log_capacity" | ||
| 23429 | " is too small for safety of redo log files." | ||
| 23430 | " Consider increasing it or decreasing" | ||
| 23431 | " innodb_thread_concurrency."); | ||
| 23432 | } | ||
| 23433 | } | ||
| 23434 | |||
| 23435 | /** Update the system variable innodb_thread_concurrency using the "saved" | ||
| 23436 | value. This function is registered as a callback with MySQL. | ||
| 23437 | @param[in] thd thread handle | ||
| 23438 | @param[in] save immediate result from check function */ | ||
| 23439 | 36 | static void innodb_thread_concurrency_update(THD *thd, SYS_VAR *, void *, | |
| 23440 | const void *save) { | ||
| 23441 | 36 | srv_thread_concurrency = *static_cast<const ulong *>(save); | |
| 23442 | |||
| 23443 | 36 | ib::info(ER_IB_MSG_THREAD_CONCURRENCY_CHANGED, srv_thread_concurrency); | |
| 23444 | |||
| 23445 | 36 | log_files_thread_concurrency_updated(*log_sys); | |
| 23446 | |||
| 23447 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 33 times.
|
36 | if (!log_sys->concurrency_margin_is_safe.load()) { |
| 23448 | 3 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23449 | "Current innodb_thread_concurrency" | ||
| 23450 | " is too big for safety of redo log files." | ||
| 23451 | " Consider decreasing it or increasing" | ||
| 23452 | " innodb_redo_log_capacity."); | ||
| 23453 | } | ||
| 23454 | 36 | } | |
| 23455 | |||
| 23456 | /** Empty free list algorithm. This function is registered as a callback with | ||
| 23457 | MySQL. | ||
| 23458 | @param[in] thd thread handle | ||
| 23459 | @param[in] var pointer to system variable | ||
| 23460 | @param[out] save immediate result for update function | ||
| 23461 | @param[in] value incoming string | ||
| 23462 | @return 0 for valid algorithm */ | ||
| 23463 | 13 | static int innodb_srv_empty_free_list_algorithm_validate( | |
| 23464 | THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value) { | ||
| 23465 | char buff[STRING_BUFFER_USUAL_SIZE]; | ||
| 23466 | 13 | int len = sizeof(buff); | |
| 23467 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | const char *const algorithm_name = value->val_str(value, buff, &len); |
| 23468 | |||
| 23469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!algorithm_name) return (1); |
| 23470 | |||
| 23471 | ulint algo; | ||
| 23472 | 22 | for (algo = 0; | |
| 23473 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
|
22 | algo < array_elements(innodb_empty_free_list_algorithm_names) - 1; |
| 23474 | algo++) { | ||
| 23475 |
3/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 9 times.
|
20 | if (!innobase_strcasecmp(algorithm_name, |
| 23476 | innodb_empty_free_list_algorithm_names[algo])) | ||
| 23477 | 11 | break; | |
| 23478 | } | ||
| 23479 | |||
| 23480 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
|
13 | if (algo == array_elements(innodb_empty_free_list_algorithm_names) - 1) |
| 23481 | 2 | return (1); | |
| 23482 | |||
| 23483 | 11 | const auto algorithm = static_cast<srv_empty_free_list_t>(algo); | |
| 23484 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
|
11 | if (!innodb_empty_free_list_algorithm_allowed(algorithm)) { |
| 23485 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | sql_print_warning( |
| 23486 | "InnoDB: innodb_empty_free_list_algorithm = 'backoff' " | ||
| 23487 | "requires at least 20MB buffer pool instances.\n"); | ||
| 23488 | 2 | return (1); | |
| 23489 | } | ||
| 23490 | |||
| 23491 | 9 | *reinterpret_cast<ulong *>(save) = static_cast<ulong>(algorithm); | |
| 23492 | 9 | return (0); | |
| 23493 | } | ||
| 23494 | |||
| 23495 | 10 | static int innodb_encryption_threads_validate( | |
| 23496 | /*=================================*/ | ||
| 23497 | THD *thd, /*!< in: thread handle */ | ||
| 23498 | SYS_VAR *var, /*!< in: pointer to system | ||
| 23499 | variable */ | ||
| 23500 | void *save, /*!< out: immediate result | ||
| 23501 | for update function */ | ||
| 23502 | struct st_mysql_value *value) /*!< in: incoming string */ | ||
| 23503 | { | ||
| 23504 | long long intbuf; | ||
| 23505 | |||
| 23506 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | DBUG_TRACE; |
| 23507 | |||
| 23508 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (value->val_int(value, &intbuf)) { |
| 23509 | /* The value is NULL. That is invalid. */ | ||
| 23510 | ✗ | return 1; | |
| 23511 | } | ||
| 23512 | |||
| 23513 | 10 | bool is_val_fixed = false; | |
| 23514 | 10 | long long requested_threads = intbuf; | |
| 23515 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
|
10 | if (intbuf < 0) { |
| 23516 | 2 | requested_threads = 0; | |
| 23517 | 2 | is_val_fixed = true; | |
| 23518 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
8 | } else if (intbuf > MAX_ENCRYPTION_THREADS) { |
| 23519 | 2 | requested_threads = MAX_ENCRYPTION_THREADS; | |
| 23520 | 2 | is_val_fixed = true; | |
| 23521 | } | ||
| 23522 | |||
| 23523 |
3/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
|
10 | if (throw_bounds_warning(thd, "innodb_encryption_threads", is_val_fixed, |
| 23524 | intbuf)) { | ||
| 23525 | 2 | return 1; | |
| 23526 | } | ||
| 23527 | |||
| 23528 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
|
8 | if (srv_n_fil_crypt_threads_requested == 0 && requested_threads > 0) { |
| 23529 | // We are starting encryption threads, we must lock | ||
| 23530 | // the keyring plugins | ||
| 23531 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | uint number_of_keyrings_locked = lock_keyrings(NULL); |
| 23532 | |||
| 23533 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (number_of_keyrings_locked == 0) { |
| 23534 | ✗ | my_printf_error(ER_WRONG_ARGUMENTS, | |
| 23535 | "InnoDB: cannot enable encryption threads, " | ||
| 23536 | "keyring plugin is not available", | ||
| 23537 | MYF(0)); | ||
| 23538 | ✗ | return 1; | |
| 23539 | } | ||
| 23540 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (Encryption::is_keyring_alive() == false) { |
| 23541 | ✗ | my_printf_error( | |
| 23542 | ER_WRONG_ARGUMENTS, | ||
| 23543 | "InnoDB: keyring plugin is installed but it seems it was not " | ||
| 23544 | "properly initialized. Cannot enable encryption threads.", | ||
| 23545 | MYF(0)); | ||
| 23546 | ✗ | unlock_keyrings(NULL); | |
| 23547 | ✗ | return 1; | |
| 23548 | } | ||
| 23549 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
|
8 | } else if (requested_threads == 0 && srv_n_fil_crypt_threads_requested > 0) { |
| 23550 | // We are disabling encryption | ||
| 23551 | // threads, unlock the keyrings | ||
| 23552 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | unlock_keyrings(NULL); |
| 23553 | } | ||
| 23554 | |||
| 23555 | 8 | *reinterpret_cast<ulong *>(save) = static_cast<ulong>(requested_threads); | |
| 23556 | |||
| 23557 | 8 | return 0; | |
| 23558 | 10 | } | |
| 23559 | |||
| 23560 | /****************************************************************** | ||
| 23561 | Update the system variable innodb_encryption_threads */ | ||
| 23562 | 8 | static void innodb_encryption_threads_update( | |
| 23563 | /*=============================*/ | ||
| 23564 | THD *thd, /*!< in: thread handle */ | ||
| 23565 | SYS_VAR *var, /*!< in: pointer to | ||
| 23566 | system variable */ | ||
| 23567 | void *var_ptr, /*!< out: where the | ||
| 23568 | formal string goes */ | ||
| 23569 | const void *save) /*!< in: immediate result | ||
| 23570 | from check function */ | ||
| 23571 | { | ||
| 23572 | 8 | mysql_mutex_unlock(&LOCK_global_system_variables); | |
| 23573 | 8 | fil_crypt_set_thread_cnt(*static_cast<const uint *>(save)); | |
| 23574 | 8 | mysql_mutex_lock(&LOCK_global_system_variables); | |
| 23575 | 8 | } | |
| 23576 | |||
| 23577 | /****************************************************************** | ||
| 23578 | Update the system variable innodb_encryption_rotate_key_age */ | ||
| 23579 | 3 | static void innodb_encryption_rotate_key_age_update( | |
| 23580 | /*====================================*/ | ||
| 23581 | THD *thd, /*!< in: thread handle */ | ||
| 23582 | SYS_VAR *var, /*!< in: pointer to | ||
| 23583 | system variable */ | ||
| 23584 | void *var_ptr, /*!< out: where the | ||
| 23585 | formal string goes */ | ||
| 23586 | const void *save) /*!< in: immediate result | ||
| 23587 | from check function */ | ||
| 23588 | { | ||
| 23589 | 3 | fil_crypt_set_rotate_key_age(*static_cast<const uint *>(save)); | |
| 23590 | 3 | } | |
| 23591 | |||
| 23592 | /****************************************************************** | ||
| 23593 | Update the system variable innodb_encryption_rotation_iops */ | ||
| 23594 | 3 | static void innodb_encryption_rotation_iops_update( | |
| 23595 | /*===================================*/ | ||
| 23596 | THD *thd, /*!< in: thread handle */ | ||
| 23597 | SYS_VAR *var, /*!< in: pointer to | ||
| 23598 | system variable */ | ||
| 23599 | void *var_ptr, /*!< out: where the | ||
| 23600 | formal string goes */ | ||
| 23601 | const void *save) /*!< in: immediate result | ||
| 23602 | from check function */ | ||
| 23603 | { | ||
| 23604 | 3 | fil_crypt_set_rotation_iops(*static_cast<const uint *>(save)); | |
| 23605 | 3 | } | |
| 23606 | |||
| 23607 | /** Update the innodb_log_checksums parameter. | ||
| 23608 | @param[out] var_ptr current value | ||
| 23609 | @param[in] save immediate result from check function */ | ||
| 23610 | 7 | static void innodb_log_checksums_update(THD *, SYS_VAR *, void *var_ptr, | |
| 23611 | const void *save) { | ||
| 23612 | 7 | bool check = *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 23613 | |||
| 23614 | /* Make sure we are the only log user */ | ||
| 23615 | 7 | innodb_log_checksums_func_update(check); | |
| 23616 | 7 | } | |
| 23617 | |||
| 23618 | /** Enable or disable encryption of temporary tablespace | ||
| 23619 | @param[in] thd thread handle | ||
| 23620 | @param[in] var system variable | ||
| 23621 | @param[out] var_ptr current value | ||
| 23622 | @param[in] save immediate result from check function */ | ||
| 23623 | 69 | static void innodb_temp_tablespace_encryption_update(THD *thd, SYS_VAR *var, | |
| 23624 | void *var_ptr, | ||
| 23625 | const void *save) { | ||
| 23626 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 68 times.
|
69 | if (srv_read_only_mode) { |
| 23627 | 1 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23628 | " Temporary tablespace cannot be" | ||
| 23629 | " encrypted in innodb_read_only mode"); | ||
| 23630 | 1 | return; | |
| 23631 | } | ||
| 23632 | |||
| 23633 | 68 | bool check = *static_cast<const bool *>(save); | |
| 23634 | |||
| 23635 | 68 | dberr_t err = srv_temp_encryption_update(check); | |
| 23636 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
|
68 | if (err != DB_SUCCESS) { |
| 23637 | 2 | push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS, | |
| 23638 | " Temporary tablespace couldn't be" | ||
| 23639 | " encrypted. Check if keyring plugin" | ||
| 23640 | " is loaded."); | ||
| 23641 | } else { | ||
| 23642 | 66 | *static_cast<bool *>(var_ptr) = *static_cast<const bool *>(save); | |
| 23643 | } | ||
| 23644 | } | ||
| 23645 | |||
| 23646 | static SHOW_VAR innodb_status_variables_export[] = { | ||
| 23647 | {"Innodb", (char *)&show_innodb_vars, SHOW_FUNC, SHOW_SCOPE_GLOBAL}, | ||
| 23648 | {NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL}}; | ||
| 23649 | |||
| 23650 | static struct st_mysql_storage_engine innobase_storage_engine = { | ||
| 23651 | MYSQL_HANDLERTON_INTERFACE_VERSION}; | ||
| 23652 | |||
| 23653 | /* plugin options */ | ||
| 23654 | |||
| 23655 | static MYSQL_SYSVAR_ENUM( | ||
| 23656 | checksum_algorithm, srv_checksum_algorithm, PLUGIN_VAR_RQCMDARG, | ||
| 23657 | "The algorithm InnoDB uses for page checksumming. Possible values are" | ||
| 23658 | " CRC32 (hardware accelerated if the CPU supports it)" | ||
| 23659 | " write crc32, allow any of the other checksums to match when reading;" | ||
| 23660 | " STRICT_CRC32" | ||
| 23661 | " write crc32, do not allow other algorithms to match when reading;" | ||
| 23662 | " INNODB" | ||
| 23663 | " write a software calculated checksum, allow any other checksums" | ||
| 23664 | " to match when reading;" | ||
| 23665 | " STRICT_INNODB" | ||
| 23666 | " write a software calculated checksum, do not allow other algorithms" | ||
| 23667 | " to match when reading;" | ||
| 23668 | " NONE" | ||
| 23669 | " write a constant magic number, do not do any checksum verification" | ||
| 23670 | " when reading;" | ||
| 23671 | " STRICT_NONE" | ||
| 23672 | " write a constant magic number, do not allow values other than that" | ||
| 23673 | " magic number when reading;" | ||
| 23674 | " Files updated when this option is set to crc32 or strict_crc32 will" | ||
| 23675 | " not be readable by MySQL versions older than 5.6.3", | ||
| 23676 | nullptr, nullptr, SRV_CHECKSUM_ALGORITHM_CRC32, | ||
| 23677 | &innodb_checksum_algorithm_typelib); | ||
| 23678 | |||
| 23679 | static MYSQL_SYSVAR_BOOL( | ||
| 23680 | log_checksums, srv_log_checksums, PLUGIN_VAR_RQCMDARG, | ||
| 23681 | "Whether to compute and require checksums for InnoDB redo log blocks", | ||
| 23682 | nullptr, innodb_log_checksums_update, true); | ||
| 23683 | |||
| 23684 | static MYSQL_SYSVAR_STR(data_home_dir, innobase_data_home_dir, | ||
| 23685 | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 23686 | "The common part for InnoDB table spaces.", nullptr, | ||
| 23687 | nullptr, nullptr); | ||
| 23688 | |||
| 23689 | static MYSQL_SYSVAR_BOOL( | ||
| 23690 | stats_include_delete_marked, srv_stats_include_delete_marked, | ||
| 23691 | PLUGIN_VAR_OPCMDARG, | ||
| 23692 | "Include delete marked records when calculating persistent statistics", | ||
| 23693 | nullptr, nullptr, false); | ||
| 23694 | |||
| 23695 | static MYSQL_SYSVAR_ULONG( | ||
| 23696 | io_capacity, srv_io_capacity, PLUGIN_VAR_RQCMDARG, | ||
| 23697 | "Number of IOPs the server can do. Tunes the background IO rate", nullptr, | ||
| 23698 | innodb_io_capacity_update, 200, 100, ~0UL, 0); | ||
| 23699 | |||
| 23700 | static MYSQL_SYSVAR_ULONG(io_capacity_max, srv_max_io_capacity, | ||
| 23701 | PLUGIN_VAR_RQCMDARG, | ||
| 23702 | "Limit to which innodb_io_capacity can be inflated.", | ||
| 23703 | nullptr, innodb_io_capacity_max_update, | ||
| 23704 | SRV_MAX_IO_CAPACITY_DUMMY_DEFAULT, 100, | ||
| 23705 | SRV_MAX_IO_CAPACITY_LIMIT, 0); | ||
| 23706 | |||
| 23707 | #ifdef UNIV_DEBUG | ||
| 23708 | static MYSQL_SYSVAR_BOOL(background_drop_list_empty, | ||
| 23709 | innodb_background_drop_list_empty, PLUGIN_VAR_OPCMDARG, | ||
| 23710 | "Wait for the background drop list to become empty", | ||
| 23711 | nullptr, wait_background_drop_list_empty, false); | ||
| 23712 | |||
| 23713 | static MYSQL_SYSVAR_BOOL(purge_run_now, innodb_purge_run_now, | ||
| 23714 | PLUGIN_VAR_OPCMDARG, "Set purge state to RUN", nullptr, | ||
| 23715 | purge_run_now_set, false); | ||
| 23716 | |||
| 23717 | static MYSQL_SYSVAR_BOOL(purge_stop_now, innodb_purge_stop_now, | ||
| 23718 | PLUGIN_VAR_OPCMDARG, "Set purge state to STOP", | ||
| 23719 | nullptr, purge_stop_now_set, false); | ||
| 23720 | |||
| 23721 | static MYSQL_SYSVAR_BOOL(log_flush_now, innodb_log_flush_now, | ||
| 23722 | PLUGIN_VAR_OPCMDARG, | ||
| 23723 | "Force flush of redo up to current lsn", nullptr, | ||
| 23724 | log_flush_now_set, false); | ||
| 23725 | |||
| 23726 | static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now, | ||
| 23727 | PLUGIN_VAR_OPCMDARG, "Force sharp checkpoint now", | ||
| 23728 | nullptr, checkpoint_now_set, false); | ||
| 23729 | |||
| 23730 | static MYSQL_SYSVAR_BOOL(log_checkpoint_fuzzy_now, | ||
| 23731 | innodb_log_checkpoint_fuzzy_now, PLUGIN_VAR_OPCMDARG, | ||
| 23732 | "Force fuzzy checkpoint now", nullptr, | ||
| 23733 | checkpoint_fuzzy_now_set, false); | ||
| 23734 | |||
| 23735 | static MYSQL_SYSVAR_BOOL(checkpoint_disabled, srv_checkpoint_disabled, | ||
| 23736 | PLUGIN_VAR_OPCMDARG, "Disable checkpoints", nullptr, | ||
| 23737 | checkpoint_disabled_update, false); | ||
| 23738 | |||
| 23739 | static MYSQL_SYSVAR_BOOL(buf_flush_list_now, innodb_buf_flush_list_now, | ||
| 23740 | PLUGIN_VAR_OPCMDARG, "Force dirty page flush now", | ||
| 23741 | nullptr, buf_flush_list_now_set, false); | ||
| 23742 | |||
| 23743 | static MYSQL_SYSVAR_UINT( | ||
| 23744 | merge_threshold_set_all_debug, innodb_merge_threshold_set_all_debug, | ||
| 23745 | PLUGIN_VAR_RQCMDARG, | ||
| 23746 | "Override current MERGE_THRESHOLD setting for all indexes at dictionary" | ||
| 23747 | " cache by the specified value dynamically, at the time.", | ||
| 23748 | nullptr, innodb_merge_threshold_set_all_debug_update, | ||
| 23749 | DICT_INDEX_MERGE_THRESHOLD_DEFAULT, 1, 50, 0); | ||
| 23750 | |||
| 23751 | extern ulong srv_fatal_semaphore_wait_threshold; | ||
| 23752 | static MYSQL_SYSVAR_ULONG( | ||
| 23753 | semaphore_wait_timeout_debug, srv_fatal_semaphore_wait_threshold, | ||
| 23754 | PLUGIN_VAR_RQCMDARG, | ||
| 23755 | "Number of seconds that a semaphore can be held. If semaphore wait crosses" | ||
| 23756 | "this value, server will crash", | ||
| 23757 | nullptr, nullptr, 600, 25, 600, 0); | ||
| 23758 | #endif /* UNIV_DEBUG */ | ||
| 23759 | |||
| 23760 | static MYSQL_SYSVAR_ULONG( | ||
| 23761 | purge_batch_size, srv_purge_batch_size, PLUGIN_VAR_OPCMDARG, | ||
| 23762 | "Number of UNDO log pages to purge in one batch from the history list.", | ||
| 23763 | nullptr, nullptr, 300, /* Default setting */ | ||
| 23764 | 1, /* Minimum value */ | ||
| 23765 | 5000, 0); /* Maximum value */ | ||
| 23766 | |||
| 23767 | static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads, | ||
| 23768 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 23769 | "Purge threads can be from 1 to 32. Default is 4.", | ||
| 23770 | nullptr, nullptr, 4, /* Default setting */ | ||
| 23771 | 1, /* Minimum value */ | ||
| 23772 | MAX_PURGE_THREADS, 0); /* Maximum value */ | ||
| 23773 | |||
| 23774 | static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size, | ||
| 23775 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 23776 | "Size of the mutex/lock wait array.", nullptr, | ||
| 23777 | nullptr, 1, /* Default setting */ | ||
| 23778 | 1, /* Minimum value */ | ||
| 23779 | 1024, 0); /* Maximum value */ | ||
| 23780 | |||
| 23781 | static MYSQL_SYSVAR_ULONG( | ||
| 23782 | fast_shutdown, srv_fast_shutdown, PLUGIN_VAR_OPCMDARG, | ||
| 23783 | "Speeds up the shutdown process of the InnoDB storage engine. Possible" | ||
| 23784 | " values are 0, 1 (faster) or 2 (fastest - crash-like).", | ||
| 23785 | nullptr, nullptr, 1, 0, 2, 0); | ||
| 23786 | |||
| 23787 | static MYSQL_SYSVAR_BOOL( | ||
| 23788 | file_per_table, srv_file_per_table, PLUGIN_VAR_NOCMDARG, | ||
| 23789 | "Stores each InnoDB table to an .ibd file in the database dir.", nullptr, | ||
| 23790 | nullptr, true); | ||
| 23791 | |||
| 23792 | static MYSQL_SYSVAR_STR(ft_server_stopword_table, | ||
| 23793 | innobase_server_stopword_table, | ||
| 23794 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 23795 | "The user supplied stopword table name.", | ||
| 23796 | innodb_stopword_table_validate, nullptr, nullptr); | ||
| 23797 | |||
| 23798 | extern uint srv_flush_log_at_timeout; | ||
| 23799 | static MYSQL_SYSVAR_UINT(flush_log_at_timeout, srv_flush_log_at_timeout, | ||
| 23800 | PLUGIN_VAR_OPCMDARG, | ||
| 23801 | "Write and flush logs every (n) second.", nullptr, | ||
| 23802 | nullptr, 1, 0, 2700, 0); | ||
| 23803 | |||
| 23804 | static MYSQL_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit, | ||
| 23805 | PLUGIN_VAR_OPCMDARG, | ||
| 23806 | "Set to 0 (write and flush once per second)," | ||
| 23807 | " 1 (write and flush at each commit)," | ||
| 23808 | " or 2 (write at commit, flush once per second).", | ||
| 23809 | nullptr, nullptr, 1, 0, 2, 0); | ||
| 23810 | |||
| 23811 | static MYSQL_SYSVAR_ENUM(flush_method, innodb_flush_method, | ||
| 23812 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 23813 | "With which method to flush data", nullptr, nullptr, 0, | ||
| 23814 | &innodb_flush_method_typelib); | ||
| 23815 | |||
| 23816 | static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted, | ||
| 23817 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY | | ||
| 23818 | PLUGIN_VAR_NOPERSIST, | ||
| 23819 | "Force InnoDB to load metadata of corrupted table.", | ||
| 23820 | nullptr, nullptr, false); | ||
| 23821 | |||
| 23822 | static MYSQL_SYSVAR_ULONG(show_locks_held, srv_show_locks_held, | ||
| 23823 | PLUGIN_VAR_RQCMDARG, | ||
| 23824 | "Number of locks held to print for each InnoDB " | ||
| 23825 | "transaction in SHOW INNODB STATUS.", | ||
| 23826 | NULL, NULL, 10, 0, 1000, 0); | ||
| 23827 | |||
| 23828 | static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir, | ||
| 23829 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 23830 | PLUGIN_VAR_NOPERSIST, | ||
| 23831 | "Path to InnoDB log files.", nullptr, nullptr, nullptr); | ||
| 23832 | |||
| 23833 | static MYSQL_SYSVAR_ULONG( | ||
| 23834 | page_cleaners, srv_n_page_cleaners, | ||
| 23835 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 23836 | "Page cleaner threads can be from 1 to 64. Default is 4.", nullptr, nullptr, | ||
| 23837 | 4, 1, 64, 0); | ||
| 23838 | |||
| 23839 | static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, | ||
| 23840 | PLUGIN_VAR_RQCMDARG, | ||
| 23841 | "Percentage of dirty pages allowed in bufferpool.", | ||
| 23842 | nullptr, innodb_max_dirty_pages_pct_update, 90.0, 0, | ||
| 23843 | 99.999, 0); | ||
| 23844 | |||
| 23845 | static MYSQL_SYSVAR_DOUBLE( | ||
| 23846 | max_dirty_pages_pct_lwm, srv_max_dirty_pages_pct_lwm, PLUGIN_VAR_RQCMDARG, | ||
| 23847 | "Percentage of dirty pages at which flushing kicks in.", nullptr, | ||
| 23848 | innodb_max_dirty_pages_pct_lwm_update, 10, 0, 99.999, 0); | ||
| 23849 | |||
| 23850 | static MYSQL_SYSVAR_ULONG( | ||
| 23851 | adaptive_flushing_lwm, srv_adaptive_flushing_lwm, PLUGIN_VAR_RQCMDARG, | ||
| 23852 | "Percentage of log capacity below which no adaptive flushing happens.", | ||
| 23853 | nullptr, nullptr, 10, 0, 70, 0); | ||
| 23854 | |||
| 23855 | static MYSQL_SYSVAR_BOOL( | ||
| 23856 | adaptive_flushing, srv_adaptive_flushing, PLUGIN_VAR_NOCMDARG, | ||
| 23857 | "Attempt flushing dirty pages to avoid IO bursts at checkpoints.", nullptr, | ||
| 23858 | nullptr, true); | ||
| 23859 | |||
| 23860 | static MYSQL_SYSVAR_BOOL( | ||
| 23861 | flush_sync, srv_flush_sync, PLUGIN_VAR_NOCMDARG, | ||
| 23862 | "Allow IO bursts at the checkpoints ignoring io_capacity setting.", nullptr, | ||
| 23863 | nullptr, true); | ||
| 23864 | |||
| 23865 | static MYSQL_SYSVAR_ULONG( | ||
| 23866 | flushing_avg_loops, srv_flushing_avg_loops, PLUGIN_VAR_RQCMDARG, | ||
| 23867 | "Number of iterations over which the background flushing is averaged.", | ||
| 23868 | nullptr, nullptr, 30, 1, 1000, 0); | ||
| 23869 | |||
| 23870 | static MYSQL_SYSVAR_ULONG( | ||
| 23871 | max_purge_lag, srv_max_purge_lag, PLUGIN_VAR_RQCMDARG, | ||
| 23872 | "Desired maximum length of the purge queue (0 = no limit)", nullptr, | ||
| 23873 | nullptr, 0, 0, ~0UL, 0); | ||
| 23874 | |||
| 23875 | static MYSQL_SYSVAR_ULONG(max_purge_lag_delay, srv_max_purge_lag_delay, | ||
| 23876 | PLUGIN_VAR_RQCMDARG, | ||
| 23877 | "Maximum delay of user threads in micro-seconds", | ||
| 23878 | nullptr, nullptr, 0L, /* Default seting */ | ||
| 23879 | 0L, /* Minimum value */ | ||
| 23880 | 10000000UL, 0); /* Maximum value */ | ||
| 23881 | |||
| 23882 | static MYSQL_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout, | ||
| 23883 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 23884 | "Roll back the complete transaction on lock wait " | ||
| 23885 | "timeout, for 4.x compatibility (disabled by default)", | ||
| 23886 | nullptr, nullptr, false); | ||
| 23887 | |||
| 23888 | static MYSQL_SYSVAR_BOOL( | ||
| 23889 | status_file, innobase_create_status_file, | ||
| 23890 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR, | ||
| 23891 | "Enable SHOW ENGINE INNODB STATUS output in the innodb_status.<pid> file", | ||
| 23892 | nullptr, nullptr, false); | ||
| 23893 | |||
| 23894 | static MYSQL_SYSVAR_BOOL( | ||
| 23895 | stats_on_metadata, innobase_stats_on_metadata, PLUGIN_VAR_OPCMDARG, | ||
| 23896 | "Enable statistics gathering for metadata commands such as" | ||
| 23897 | " SHOW TABLE STATUS for tables that use transient statistics (off by " | ||
| 23898 | "default)", | ||
| 23899 | nullptr, nullptr, false); | ||
| 23900 | |||
| 23901 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 23902 | stats_transient_sample_pages, srv_stats_transient_sample_pages, | ||
| 23903 | PLUGIN_VAR_RQCMDARG, | ||
| 23904 | "The number of leaf index pages to sample when calculating transient" | ||
| 23905 | " statistics (if persistent statistics are not used, default 8)", | ||
| 23906 | nullptr, nullptr, 8, 1, ~0ULL, 0); | ||
| 23907 | |||
| 23908 | static MYSQL_SYSVAR_BOOL( | ||
| 23909 | stats_persistent, srv_stats_persistent, PLUGIN_VAR_OPCMDARG, | ||
| 23910 | "InnoDB persistent statistics enabled for all tables unless overridden" | ||
| 23911 | " at table level", | ||
| 23912 | nullptr, nullptr, true); | ||
| 23913 | |||
| 23914 | static MYSQL_SYSVAR_BOOL( | ||
| 23915 | stats_auto_recalc, srv_stats_auto_recalc, PLUGIN_VAR_OPCMDARG, | ||
| 23916 | "InnoDB automatic recalculation of persistent statistics enabled for all" | ||
| 23917 | " tables unless overridden at table level (automatic recalculation is only" | ||
| 23918 | " done when InnoDB decides that the table has changed too much and needs a" | ||
| 23919 | " new statistics)", | ||
| 23920 | nullptr, nullptr, true); | ||
| 23921 | |||
| 23922 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 23923 | stats_persistent_sample_pages, srv_stats_persistent_sample_pages, | ||
| 23924 | PLUGIN_VAR_RQCMDARG, | ||
| 23925 | "The number of leaf index pages to sample when calculating persistent" | ||
| 23926 | " statistics (by ANALYZE, default 20)", | ||
| 23927 | nullptr, nullptr, 20, 1, ~0ULL, 0); | ||
| 23928 | |||
| 23929 | static MYSQL_SYSVAR_BOOL( | ||
| 23930 | adaptive_hash_index, btr_search_enabled, PLUGIN_VAR_OPCMDARG, | ||
| 23931 | "Enable InnoDB adaptive hash index (enabled by default). " | ||
| 23932 | " Disable with --skip-innodb-adaptive-hash-index.", | ||
| 23933 | nullptr, innodb_adaptive_hash_index_update, true); | ||
| 23934 | |||
| 23935 | /** Number of distinct partitions of AHI. | ||
| 23936 | Each partition is protected by its own latch and so we have parts number | ||
| 23937 | of latches protecting complete search system. */ | ||
| 23938 | static MYSQL_SYSVAR_ULONG( | ||
| 23939 | adaptive_hash_index_parts, btr_ahi_parts, | ||
| 23940 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 23941 | "Number of InnoDB Adaptive Hash Index Partitions. (default = 8). ", nullptr, | ||
| 23942 | nullptr, 8, 1, 512, 0); | ||
| 23943 | |||
| 23944 | extern ulong srv_replication_delay; | ||
| 23945 | static MYSQL_SYSVAR_ULONG( | ||
| 23946 | replication_delay, srv_replication_delay, PLUGIN_VAR_RQCMDARG, | ||
| 23947 | "Replication thread delay (ms) on the slave server if" | ||
| 23948 | " innodb_thread_concurrency is reached (0 by default)", | ||
| 23949 | nullptr, nullptr, 0, 0, ~0UL, 0); | ||
| 23950 | |||
| 23951 | static MYSQL_SYSVAR_UINT( | ||
| 23952 | compression_level, page_zip_level, PLUGIN_VAR_RQCMDARG, | ||
| 23953 | "Compression level used for compressed row format. 0 is no compression" | ||
| 23954 | ", 1 is fastest, 9 is best compression and default is 6.", | ||
| 23955 | nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0); | ||
| 23956 | |||
| 23957 | static MYSQL_SYSVAR_BOOL( | ||
| 23958 | log_compressed_pages, page_zip_log_pages, PLUGIN_VAR_OPCMDARG, | ||
| 23959 | "Enables/disables the logging of entire compressed page images." | ||
| 23960 | " InnoDB logs the compressed pages to prevent corruption if" | ||
| 23961 | " the zlib compression algorithm changes." | ||
| 23962 | " When turned OFF, InnoDB will assume that the zlib" | ||
| 23963 | " compression algorithm doesn't change.", | ||
| 23964 | nullptr, nullptr, true); | ||
| 23965 | |||
| 23966 | static MYSQL_SYSVAR_ULONG(autoextend_increment, | ||
| 23967 | sys_tablespace_auto_extend_increment, | ||
| 23968 | PLUGIN_VAR_RQCMDARG, | ||
| 23969 | "Data file autoextend increment in megabytes", | ||
| 23970 | nullptr, nullptr, 64L, 1L, 1000L, 0); | ||
| 23971 | |||
| 23972 | static MYSQL_SYSVAR_BOOL( | ||
| 23973 | dedicated_server, srv_dedicated_server, | ||
| 23974 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST | PLUGIN_VAR_READONLY, | ||
| 23975 | "Automatically scale innodb_buffer_pool_size and innodb_redo_log_capacity " | ||
| 23976 | "based on system memory. Also set innodb_flush_method=O_DIRECT_NO_FSYNC, " | ||
| 23977 | "if supported", | ||
| 23978 | nullptr, nullptr, false); | ||
| 23979 | |||
| 23980 | static MYSQL_SYSVAR_DOUBLE( | ||
| 23981 | segment_reserve_factor, fseg_reserve_pct, PLUGIN_VAR_OPCMDARG, | ||
| 23982 | "The segment_reserve_factor is the ratio x/y expressed in percentage," | ||
| 23983 | " where x is the number of free pages in the segment, and y is the total" | ||
| 23984 | " number of pages in the segment. The number of used pages in the segment" | ||
| 23985 | " is given by (y-x). The number of free pages in the segment (x) will be" | ||
| 23986 | " maintained such that the actual segment_reserve_factor will be >= the" | ||
| 23987 | " requested segment_reserve_factor, which is contained in this variable.", | ||
| 23988 | nullptr, nullptr, FSEG_RESERVE_PCT_DFLT, FSEG_RESERVE_PCT_MIN, | ||
| 23989 | FSEG_RESERVE_PCT_MAX, 0); | ||
| 23990 | |||
| 23991 | /* If the default value of innodb_buffer_pool_size is increased to be more than | ||
| 23992 | BUF_POOL_SIZE_THRESHOLD (srv/srv0start.cc), then srv_buf_pool_instances_default | ||
| 23993 | can be removed and 8 used instead. The problem with the current setup is that | ||
| 23994 | with 128MiB default buffer pool size and 8 instances by default we would emit | ||
| 23995 | a warning when no options are specified. */ | ||
| 23996 | static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, srv_buf_pool_curr_size, | ||
| 23997 | PLUGIN_VAR_RQCMDARG | | ||
| 23998 | PLUGIN_VAR_PERSIST_AS_READ_ONLY, | ||
| 23999 | "The size of the memory buffer InnoDB uses to " | ||
| 24000 | "cache data and indexes of its tables.", | ||
| 24001 | nullptr, innodb_buffer_pool_size_update, | ||
| 24002 | static_cast<longlong>(srv_buf_pool_def_size), | ||
| 24003 | static_cast<longlong>(srv_buf_pool_min_size), | ||
| 24004 | longlong{srv_buf_pool_max_size}, 1024 * 1024L); | ||
| 24005 | |||
| 24006 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 24007 | buffer_pool_chunk_size, srv_buf_pool_chunk_unit, | ||
| 24008 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24009 | "Size of a single memory chunk within each buffer pool instance" | ||
| 24010 | " for resizing buffer pool. Online buffer pool resizing happens" | ||
| 24011 | " at this granularity.", | ||
| 24012 | nullptr, nullptr, 128 * 1024 * 1024, ulonglong{srv_buf_pool_chunk_unit_min}, | ||
| 24013 | ulonglong{srv_buf_pool_chunk_unit_max}, | ||
| 24014 | ulonglong{srv_buf_pool_chunk_unit_blk_sz}); | ||
| 24015 | |||
| 24016 | #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG | ||
| 24017 | static MYSQL_SYSVAR_ULONG(page_hash_locks, srv_n_page_hash_locks, | ||
| 24018 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 24019 | "Number of rw_locks protecting buffer pool " | ||
| 24020 | "page_hash. Rounded up to the next power of 2", | ||
| 24021 | nullptr, nullptr, 16, 1, MAX_PAGE_HASH_LOCKS, 0); | ||
| 24022 | |||
| 24023 | #ifdef UNIV_LINUX | ||
| 24024 | |||
| 24025 | static MYSQL_SYSVAR_ULONG(sched_priority_purge, srv_sched_priority_purge, | ||
| 24026 | PLUGIN_VAR_RQCMDARG, | ||
| 24027 | "Nice value for the purge thread scheduling", NULL, | ||
| 24028 | innodb_sched_priority_purge_update, 19, 0, 39, 0); | ||
| 24029 | |||
| 24030 | static MYSQL_SYSVAR_ULONG(sched_priority_io, srv_sched_priority_io, | ||
| 24031 | PLUGIN_VAR_RQCMDARG, | ||
| 24032 | "Nice value for the I/O handler thread scheduling", | ||
| 24033 | NULL, innodb_sched_priority_io_update, 19, 0, 39, 0); | ||
| 24034 | |||
| 24035 | static MYSQL_SYSVAR_ULONG(sched_priority_master, srv_sched_priority_master, | ||
| 24036 | PLUGIN_VAR_RQCMDARG, | ||
| 24037 | "Nice value for the master thread scheduling", NULL, | ||
| 24038 | innodb_sched_priority_master_update, 19, 0, 39, 0); | ||
| 24039 | |||
| 24040 | static MYSQL_SYSVAR_BOOL( | ||
| 24041 | priority_purge, srv_purge_thread_priority, PLUGIN_VAR_OPCMDARG, | ||
| 24042 | "Make purge coordinator and worker threads acquire shared resources with " | ||
| 24043 | "priority", | ||
| 24044 | NULL, NULL, false); | ||
| 24045 | |||
| 24046 | static MYSQL_SYSVAR_BOOL( | ||
| 24047 | priority_master, srv_master_thread_priority, PLUGIN_VAR_OPCMDARG, | ||
| 24048 | "Make buffer pool cleaner thread acquire shared resources with priority", | ||
| 24049 | NULL, NULL, false); | ||
| 24050 | |||
| 24051 | #endif /* UNIV_LINUX */ | ||
| 24052 | |||
| 24053 | // TODO: the option is here, but currently a no-op | ||
| 24054 | static MYSQL_SYSVAR_ULONG( | ||
| 24055 | cleaner_max_lru_time, srv_cleaner_max_lru_time, PLUGIN_VAR_RQCMDARG, | ||
| 24056 | "The maximum time limit for a single LRU tail flush iteration by the page " | ||
| 24057 | "cleaner thread in miliseconds", | ||
| 24058 | NULL, NULL, 1000, 0, ~0UL, 0); | ||
| 24059 | |||
| 24060 | // TODO: the option is here, but currently a no-op | ||
| 24061 | static MYSQL_SYSVAR_ULONG(cleaner_max_flush_time, srv_cleaner_max_flush_time, | ||
| 24062 | PLUGIN_VAR_RQCMDARG, | ||
| 24063 | "The maximum time limit for a single flush list " | ||
| 24064 | "flush iteration by the page " | ||
| 24065 | "cleaner thread in miliseconds", | ||
| 24066 | NULL, NULL, 1000, 0, ~0UL, 0); | ||
| 24067 | #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ | ||
| 24068 | |||
| 24069 | static MYSQL_SYSVAR_BOOL( | ||
| 24070 | validate_tablespace_paths, srv_validate_tablespace_paths, | ||
| 24071 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 24072 | "Enable validation of tablespace paths against the DD. (enabled by " | ||
| 24073 | "default)." | ||
| 24074 | " Disable with --skip-innodb-validate-tablespace-paths.", | ||
| 24075 | nullptr, nullptr, true); | ||
| 24076 | |||
| 24077 | static MYSQL_SYSVAR_BOOL(use_fdatasync, srv_use_fdatasync, PLUGIN_VAR_NOCMDARG, | ||
| 24078 | "Use fdatasync() instead of the default fsync().", | ||
| 24079 | nullptr, nullptr, false); | ||
| 24080 | |||
| 24081 | // clang-format off | ||
| 24082 | static MYSQL_SYSVAR_ENUM( | ||
| 24083 | doublewrite, dblwr::g_mode, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 24084 | "Enable InnoDB doublewrite buffer (enabled by default)." | ||
| 24085 | " Disable with --skip-innodb-doublewrite.", | ||
| 24086 | nullptr, doublewrite_update, dblwr::Mode::ON, &innodb_doublewrite_typelib); | ||
| 24087 | |||
| 24088 | static MYSQL_SYSVAR_BOOL( | ||
| 24089 | extend_and_initialize, tbsp_extend_and_initialize, PLUGIN_VAR_NOCMDARG, | ||
| 24090 | "Initialize the allocated space by writing zeros (enabled by default).", | ||
| 24091 | nullptr, innodb_extend_and_initialize_update, true); | ||
| 24092 | |||
| 24093 | static MYSQL_SYSVAR_STR( | ||
| 24094 | doublewrite_dir, innobase_doublewrite_dir, PLUGIN_VAR_READONLY, | ||
| 24095 | "Use a separate directory for the doublewrite buffer files, ", nullptr, nullptr, | ||
| 24096 | nullptr); | ||
| 24097 | |||
| 24098 | static MYSQL_SYSVAR_ULONG( | ||
| 24099 | doublewrite_pages, dblwr::n_pages, | ||
| 24100 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24101 | "Number of double write pages per thread" , nullptr, nullptr, 0, 0, 512, 0); | ||
| 24102 | |||
| 24103 | static MYSQL_SYSVAR_ULONG( | ||
| 24104 | doublewrite_files, dblwr::n_files, | ||
| 24105 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24106 | "Number of double write files", nullptr, nullptr, 0, 0, 256, 0); | ||
| 24107 | |||
| 24108 | static MYSQL_SYSVAR_ULONG( | ||
| 24109 | doublewrite_batch_size, dblwr::batch_size, | ||
| 24110 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24111 | "Number of double write pages to write in a batch", nullptr, nullptr, | ||
| 24112 | 0, 0, 256, 0); | ||
| 24113 | // clang-format on | ||
| 24114 | |||
| 24115 | static MYSQL_SYSVAR_ENUM( | ||
| 24116 | cleaner_lsn_age_factor, srv_cleaner_lsn_age_factor, PLUGIN_VAR_OPCMDARG, | ||
| 24117 | "The formula for LSN age factor for page cleaner adaptive flushing. " | ||
| 24118 | "LEGACY: Original Oracle MySQL formula. " | ||
| 24119 | "HIGH_CHECKPOINT: (the default) Percona Server formula.", | ||
| 24120 | nullptr, nullptr, SRV_CLEANER_LSN_AGE_FACTOR_HIGH_CHECKPOINT, | ||
| 24121 | &innodb_cleaner_lsn_age_factor_typelib); | ||
| 24122 | |||
| 24123 | static MYSQL_SYSVAR_ENUM( | ||
| 24124 | empty_free_list_algorithm, srv_empty_free_list_algorithm, | ||
| 24125 | PLUGIN_VAR_OPCMDARG, | ||
| 24126 | "The algorithm to use for empty free list handling. Allowed values: " | ||
| 24127 | "LEGACY: (the default) Original Oracle MySQL handling with single page " | ||
| 24128 | "flushes; " | ||
| 24129 | "BACKOFF: Wait until cleaner produces a free page.", | ||
| 24130 | innodb_srv_empty_free_list_algorithm_validate, nullptr, | ||
| 24131 | SRV_EMPTY_FREE_LIST_LEGACY, &innodb_empty_free_list_algorithm_typelib); | ||
| 24132 | |||
| 24133 | static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances, | ||
| 24134 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24135 | "Number of buffer pool instances, set to higher " | ||
| 24136 | "value on high-end machines to increase scalability", | ||
| 24137 | nullptr, nullptr, srv_buf_pool_instances_default, 0, | ||
| 24138 | MAX_BUFFER_POOLS, 0); | ||
| 24139 | |||
| 24140 | static MYSQL_SYSVAR_STR( | ||
| 24141 | buffer_pool_filename, srv_buf_dump_filename, | ||
| 24142 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 24143 | "Filename to/from which to dump/load the InnoDB buffer pool", | ||
| 24144 | innodb_srv_buf_dump_filename_validate, nullptr, | ||
| 24145 | SRV_BUF_DUMP_FILENAME_DEFAULT); | ||
| 24146 | |||
| 24147 | static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now, | ||
| 24148 | PLUGIN_VAR_RQCMDARG, | ||
| 24149 | "Trigger an immediate dump of the buffer pool into a " | ||
| 24150 | "file named @@innodb_buffer_pool_filename", | ||
| 24151 | nullptr, buffer_pool_dump_now, false); | ||
| 24152 | |||
| 24153 | static MYSQL_SYSVAR_BOOL( | ||
| 24154 | buffer_pool_dump_at_shutdown, srv_buffer_pool_dump_at_shutdown, | ||
| 24155 | PLUGIN_VAR_RQCMDARG, | ||
| 24156 | "Dump the buffer pool into a file named @@innodb_buffer_pool_filename", | ||
| 24157 | nullptr, nullptr, true); | ||
| 24158 | |||
| 24159 | static MYSQL_SYSVAR_BOOL( | ||
| 24160 | buffer_pool_in_core_file, srv_buffer_pool_in_core_file, PLUGIN_VAR_NOCMDARG, | ||
| 24161 | "This option has no effect if @@core_file is OFF. " | ||
| 24162 | "If @@core_file is ON, and this option is OFF, then the core dump file will" | ||
| 24163 | " be generated only if it is possible to exclude buffer pool from it. " | ||
| 24164 | "As soon as it will be determined that such exclusion is impossible a " | ||
| 24165 | "warning will be emitted and @@core_file will be set to OFF to prevent " | ||
| 24166 | "generating a core dump. " | ||
| 24167 | "If this option is enabled (which is the default), then core dumping " | ||
| 24168 | "logic will not be affected. ", | ||
| 24169 | nullptr, innodb_srv_buffer_pool_in_core_file_update, true); | ||
| 24170 | |||
| 24171 | static MYSQL_SYSVAR_ULONG( | ||
| 24172 | buffer_pool_dump_pct, srv_buf_pool_dump_pct, PLUGIN_VAR_RQCMDARG, | ||
| 24173 | "Dump only the hottest N% of each buffer pool, defaults to 25", nullptr, | ||
| 24174 | nullptr, 25, 1, 100, 0); | ||
| 24175 | |||
| 24176 | static MYSQL_SYSVAR_ULONG( | ||
| 24177 | idle_flush_pct, srv_idle_flush_pct, PLUGIN_VAR_RQCMDARG, | ||
| 24178 | "Up to what percentage of dirty pages to be flushed when server is found" | ||
| 24179 | " idle.", | ||
| 24180 | nullptr, nullptr, srv_idle_flush_pct_default, 0, 100, 0); | ||
| 24181 | |||
| 24182 | #ifdef UNIV_DEBUG | ||
| 24183 | static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict, | ||
| 24184 | PLUGIN_VAR_RQCMDARG, "Evict pages from the buffer pool", | ||
| 24185 | nullptr, innodb_buffer_pool_evict_update, ""); | ||
| 24186 | #endif /* UNIV_DEBUG */ | ||
| 24187 | |||
| 24188 | static MYSQL_SYSVAR_BOOL(buffer_pool_load_now, innodb_buffer_pool_load_now, | ||
| 24189 | PLUGIN_VAR_RQCMDARG, | ||
| 24190 | "Trigger an immediate load of the buffer pool from a " | ||
| 24191 | "file named @@innodb_buffer_pool_filename", | ||
| 24192 | nullptr, buffer_pool_load_now, false); | ||
| 24193 | |||
| 24194 | static MYSQL_SYSVAR_BOOL(buffer_pool_load_abort, innodb_buffer_pool_load_abort, | ||
| 24195 | PLUGIN_VAR_RQCMDARG, | ||
| 24196 | "Abort a currently running load of the buffer pool", | ||
| 24197 | nullptr, buffer_pool_load_abort, false); | ||
| 24198 | |||
| 24199 | /* there is no point in changing this during runtime, thus readonly */ | ||
| 24200 | static MYSQL_SYSVAR_BOOL( | ||
| 24201 | buffer_pool_load_at_startup, srv_buffer_pool_load_at_startup, | ||
| 24202 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 24203 | "Load the buffer pool from a file named @@innodb_buffer_pool_filename", | ||
| 24204 | nullptr, nullptr, true); | ||
| 24205 | |||
| 24206 | static MYSQL_SYSVAR_ULONG(lru_scan_depth, srv_LRU_scan_depth, | ||
| 24207 | PLUGIN_VAR_RQCMDARG, | ||
| 24208 | "How deep to scan LRU to keep it clean", nullptr, | ||
| 24209 | nullptr, 1024, 100, ~0UL, 0); | ||
| 24210 | |||
| 24211 | static MYSQL_SYSVAR_ULONG(flush_neighbors, srv_flush_neighbors, | ||
| 24212 | PLUGIN_VAR_OPCMDARG, | ||
| 24213 | "Set to 0 (don't flush neighbors from buffer pool)," | ||
| 24214 | " 1 (flush contiguous neighbors from buffer pool)" | ||
| 24215 | " or 2 (flush neighbors from buffer pool)," | ||
| 24216 | " when flushing a block", | ||
| 24217 | nullptr, nullptr, 0, 0, 2, 0); | ||
| 24218 | |||
| 24219 | static MYSQL_SYSVAR_ULONG( | ||
| 24220 | commit_concurrency, innobase_commit_concurrency, PLUGIN_VAR_RQCMDARG, | ||
| 24221 | "Helps in performance tuning in heavily concurrent environments.", | ||
| 24222 | innobase_commit_concurrency_validate, nullptr, 0, 0, 1000, 0); | ||
| 24223 | |||
| 24224 | static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter, | ||
| 24225 | PLUGIN_VAR_RQCMDARG, | ||
| 24226 | "Number of times a thread is allowed to enter InnoDB " | ||
| 24227 | "within the same SQL query after it has once got the " | ||
| 24228 | "ticket", | ||
| 24229 | nullptr, nullptr, 5000L, 1L, UINT_MAX, 0); | ||
| 24230 | |||
| 24231 | static MYSQL_SYSVAR_BOOL( | ||
| 24232 | deadlock_detect, innobase_deadlock_detect, PLUGIN_VAR_NOCMDARG, | ||
| 24233 | "Enable/disable InnoDB deadlock detector (default ON)." | ||
| 24234 | " if set to OFF, deadlock detection is skipped," | ||
| 24235 | " and we rely on innodb_lock_wait_timeout in case of deadlock.", | ||
| 24236 | nullptr, innobase_deadlock_detect_update, true); | ||
| 24237 | |||
| 24238 | static MYSQL_SYSVAR_LONG(fill_factor, ddl::fill_factor, PLUGIN_VAR_RQCMDARG, | ||
| 24239 | "Percentage of B-tree page filled during bulk insert", | ||
| 24240 | nullptr, nullptr, 100, 10, 100, 0); | ||
| 24241 | |||
| 24242 | static MYSQL_SYSVAR_BOOL( | ||
| 24243 | ft_enable_diag_print, fts_enable_diag_print, PLUGIN_VAR_OPCMDARG, | ||
| 24244 | "Whether to enable additional FTS diagnostic printout ", nullptr, nullptr, | ||
| 24245 | false); | ||
| 24246 | |||
| 24247 | static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache, | ||
| 24248 | PLUGIN_VAR_OPCMDARG, | ||
| 24249 | "Whether to disable OS system file cache for sort I/O", | ||
| 24250 | nullptr, nullptr, false); | ||
| 24251 | |||
| 24252 | static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name, | ||
| 24253 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 24254 | "FTS internal auxiliary table to be checked", | ||
| 24255 | innodb_internal_table_validate, nullptr, nullptr); | ||
| 24256 | |||
| 24257 | static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size, | ||
| 24258 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24259 | "InnoDB Fulltext search cache size in bytes", nullptr, | ||
| 24260 | nullptr, 8000000, 1600000, 80000000, 0); | ||
| 24261 | |||
| 24262 | static MYSQL_SYSVAR_ULONG( | ||
| 24263 | ft_total_cache_size, fts_max_total_cache_size, | ||
| 24264 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24265 | "Total memory allocated for InnoDB Fulltext Search cache", nullptr, nullptr, | ||
| 24266 | 640000000, 32000000, 1600000000, 0); | ||
| 24267 | |||
| 24268 | static MYSQL_SYSVAR_ULONG( | ||
| 24269 | ft_result_cache_limit, fts_result_cache_limit, PLUGIN_VAR_RQCMDARG, | ||
| 24270 | "InnoDB Fulltext search query result cache limit in bytes", nullptr, | ||
| 24271 | nullptr, 2000000000L, 1000000L, 4294967295UL, 0); | ||
| 24272 | |||
| 24273 | static MYSQL_SYSVAR_ULONG( | ||
| 24274 | ft_min_token_size, fts_min_token_size, | ||
| 24275 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24276 | "InnoDB Fulltext search minimum token size in characters", nullptr, nullptr, | ||
| 24277 | 3, 0, 16, 0); | ||
| 24278 | |||
| 24279 | static MYSQL_SYSVAR_ULONG( | ||
| 24280 | ft_max_token_size, fts_max_token_size, | ||
| 24281 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24282 | "InnoDB Fulltext search maximum token size in characters", nullptr, nullptr, | ||
| 24283 | FTS_MAX_WORD_LEN_IN_CHAR, 10, FTS_MAX_WORD_LEN_IN_CHAR, 0); | ||
| 24284 | |||
| 24285 | static MYSQL_SYSVAR_ULONG(ft_num_word_optimize, fts_num_word_optimize, | ||
| 24286 | PLUGIN_VAR_OPCMDARG, | ||
| 24287 | "InnoDB Fulltext search number of words to optimize " | ||
| 24288 | "for each optimize table call ", | ||
| 24289 | nullptr, nullptr, 2000, 1000, 10000, 0); | ||
| 24290 | |||
| 24291 | static MYSQL_SYSVAR_ULONG(ft_sort_pll_degree, ddl::fts_parser_threads, | ||
| 24292 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24293 | "InnoDB Fulltext search parallel sort degree, will " | ||
| 24294 | "round up to nearest power of 2 number", | ||
| 24295 | nullptr, nullptr, 2, 1, 16, 0); | ||
| 24296 | |||
| 24297 | static MYSQL_SYSVAR_ULONG(sort_buffer_size, srv_sort_buf_size, | ||
| 24298 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24299 | "Memory buffer size for index creation", nullptr, | ||
| 24300 | nullptr, 1048576, 65536, 64 << 20, 0); | ||
| 24301 | |||
| 24302 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 24303 | online_alter_log_max_size, srv_online_max_size, PLUGIN_VAR_RQCMDARG, | ||
| 24304 | "Maximum modification log file size for online index creation", nullptr, | ||
| 24305 | nullptr, 128 << 20, 65536, ~0ULL, 0); | ||
| 24306 | |||
| 24307 | static MYSQL_SYSVAR_BOOL(optimize_fulltext_only, innodb_optimize_fulltext_only, | ||
| 24308 | PLUGIN_VAR_NOCMDARG, | ||
| 24309 | "Only optimize the Fulltext index of the table", | ||
| 24310 | nullptr, nullptr, false); | ||
| 24311 | |||
| 24312 | static MYSQL_SYSVAR_ULONG(read_io_threads, srv_n_read_io_threads, | ||
| 24313 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24314 | "Number of background read I/O threads in InnoDB.", | ||
| 24315 | nullptr, nullptr, 4, 1, 64, 0); | ||
| 24316 | |||
| 24317 | static MYSQL_SYSVAR_ULONG(write_io_threads, srv_n_write_io_threads, | ||
| 24318 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24319 | "Number of background write I/O threads in InnoDB.", | ||
| 24320 | nullptr, nullptr, 4, 1, 64, 0); | ||
| 24321 | |||
| 24322 | static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery, | ||
| 24323 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24324 | "Helps to save your data in case the disk image of " | ||
| 24325 | "the database becomes corrupt.", | ||
| 24326 | nullptr, nullptr, 0, 0, 6, 0); | ||
| 24327 | |||
| 24328 | #ifdef UNIV_DEBUG | ||
| 24329 | static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash, | ||
| 24330 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24331 | "Kills the server during crash recovery.", nullptr, | ||
| 24332 | nullptr, 0, 0, 100, 0); | ||
| 24333 | #endif /* UNIV_DEBUG */ | ||
| 24334 | |||
| 24335 | static MYSQL_SYSVAR_ULONG(page_size, srv_page_size, | ||
| 24336 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY | | ||
| 24337 | PLUGIN_VAR_NOPERSIST, | ||
| 24338 | "Page size to use for all InnoDB tablespaces.", | ||
| 24339 | nullptr, nullptr, UNIV_PAGE_SIZE_DEF, | ||
| 24340 | UNIV_PAGE_SIZE_MIN, UNIV_PAGE_SIZE_MAX, 0); | ||
| 24341 | |||
| 24342 | static MYSQL_SYSVAR_ULONG( | ||
| 24343 | log_buffer_size, srv_log_buffer_size, PLUGIN_VAR_RQCMDARG, | ||
| 24344 | "The size of the buffer which InnoDB uses to write log to the log files" | ||
| 24345 | " on disk.", | ||
| 24346 | nullptr, innodb_log_buffer_size_update, INNODB_LOG_BUFFER_SIZE_DEFAULT, | ||
| 24347 | INNODB_LOG_BUFFER_SIZE_MIN, INNODB_LOG_BUFFER_SIZE_MAX, 1024); | ||
| 24348 | |||
| 24349 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 24350 | log_file_size, srv_log_file_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24351 | "Size of each log file before upgrading to 8.0.30. Deprecated.", nullptr, | ||
| 24352 | nullptr, 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L); | ||
| 24353 | |||
| 24354 | static MYSQL_SYSVAR_ULONG( | ||
| 24355 | log_files_in_group, srv_log_n_files, | ||
| 24356 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24357 | "Number of log files before upgrading to 8.0.30. Deprecated.", nullptr, | ||
| 24358 | nullptr, 2, 2, 100, 0); | ||
| 24359 | |||
| 24360 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 24361 | redo_log_capacity, srv_redo_log_capacity, | ||
| 24362 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_PERSIST_AS_READ_ONLY, | ||
| 24363 | "Limitation for total size of redo log files on disk (expressed in bytes).", | ||
| 24364 | nullptr, innodb_redo_log_capacity_update, 100 * 1024 * 1024, | ||
| 24365 | LOG_CAPACITY_MIN, LOG_CAPACITY_MAX, MB); | ||
| 24366 | |||
| 24367 | #ifdef UNIV_DEBUG_DEDICATED | ||
| 24368 | static MYSQL_SYSVAR_ULONG( | ||
| 24369 | debug_sys_mem_size, srv_debug_system_mem_size, | ||
| 24370 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24371 | "System memory size. It's for debuging dedicated server.", NULL, NULL, | ||
| 24372 | 48 * 1024 * 1024L, 4 * 1024 * 1024L, ULLONG_MAX, 1024 * 1024L); | ||
| 24373 | #endif /* UNIV_DEBUG_DEDICATED */ | ||
| 24374 | |||
| 24375 | static MYSQL_SYSVAR_ULONG(log_write_ahead_size, srv_log_write_ahead_size, | ||
| 24376 | PLUGIN_VAR_RQCMDARG, | ||
| 24377 | "Log write ahead unit size to avoid read-on-write," | ||
| 24378 | " it should match the OS cache block IO size.", | ||
| 24379 | nullptr, innodb_log_write_ahead_size_update, | ||
| 24380 | INNODB_LOG_WRITE_AHEAD_SIZE_DEFAULT, | ||
| 24381 | INNODB_LOG_WRITE_AHEAD_SIZE_MIN, | ||
| 24382 | INNODB_LOG_WRITE_AHEAD_SIZE_MAX, | ||
| 24383 | OS_FILE_LOG_BLOCK_SIZE); | ||
| 24384 | |||
| 24385 | static MYSQL_SYSVAR_BOOL( | ||
| 24386 | log_writer_threads, srv_log_writer_threads, PLUGIN_VAR_RQCMDARG, | ||
| 24387 | "Whether the log writer threads should be activated (ON), or write/flush " | ||
| 24388 | "of the redo log should be done by each thread individually (OFF).", | ||
| 24389 | nullptr, innodb_log_writer_threads_update, true); | ||
| 24390 | |||
| 24391 | static MYSQL_SYSVAR_UINT( | ||
| 24392 | log_spin_cpu_abs_lwm, srv_log_spin_cpu_abs_lwm, PLUGIN_VAR_RQCMDARG, | ||
| 24393 | "Minimum value of cpu time for which spin-delay is used." | ||
| 24394 | " Expressed in percentage of single cpu core.", | ||
| 24395 | nullptr, nullptr, INNODB_LOG_SPIN_CPU_ABS_LWM_DEFAULT, 0, UINT_MAX, 0); | ||
| 24396 | |||
| 24397 | static MYSQL_SYSVAR_UINT( | ||
| 24398 | log_spin_cpu_pct_hwm, srv_log_spin_cpu_pct_hwm, PLUGIN_VAR_RQCMDARG, | ||
| 24399 | "Maximum value of cpu time for which spin-delay is used." | ||
| 24400 | " Expressed in percentage of all cpu cores.", | ||
| 24401 | nullptr, nullptr, INNODB_LOG_SPIN_CPU_PCT_HWM_DEFAULT, 0, 100, 0); | ||
| 24402 | |||
| 24403 | static MYSQL_SYSVAR_ULONG( | ||
| 24404 | log_wait_for_flush_spin_hwm, srv_log_wait_for_flush_spin_hwm, | ||
| 24405 | PLUGIN_VAR_RQCMDARG, | ||
| 24406 | "Maximum value of average log flush time for which spin-delay is used." | ||
| 24407 | " When flushing takes longer, user threads no longer spin when waiting for" | ||
| 24408 | "flushed redo. Expressed in microseconds.", | ||
| 24409 | nullptr, nullptr, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_HWM_DEFAULT, 0, ULONG_MAX, | ||
| 24410 | 0); | ||
| 24411 | |||
| 24412 | #ifdef ENABLE_EXPERIMENT_SYSVARS | ||
| 24413 | |||
| 24414 | static MYSQL_SYSVAR_ULONG( | ||
| 24415 | log_write_events, srv_log_write_events, | ||
| 24416 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24417 | "Number of events used for notifications about log write.", NULL, NULL, | ||
| 24418 | INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0); | ||
| 24419 | |||
| 24420 | static MYSQL_SYSVAR_ULONG( | ||
| 24421 | log_flush_events, srv_log_flush_events, | ||
| 24422 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24423 | "Number of events used for notifications about log flush.", NULL, NULL, | ||
| 24424 | INNODB_LOG_EVENTS_DEFAULT, INNODB_LOG_EVENTS_MIN, INNODB_LOG_EVENTS_MAX, 0); | ||
| 24425 | |||
| 24426 | static MYSQL_SYSVAR_ULONG( | ||
| 24427 | log_recent_written_size, srv_log_recent_written_size, | ||
| 24428 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24429 | "Size of a small buffer, which allows concurrent writes to log buffer.", | ||
| 24430 | NULL, NULL, INNODB_LOG_RECENT_WRITTEN_SIZE_DEFAULT, | ||
| 24431 | INNODB_LOG_RECENT_WRITTEN_SIZE_MIN, INNODB_LOG_RECENT_WRITTEN_SIZE_MAX, 0); | ||
| 24432 | |||
| 24433 | static MYSQL_SYSVAR_ULONG( | ||
| 24434 | log_recent_closed_size, srv_log_recent_closed_size, | ||
| 24435 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24436 | "Size of a small buffer, which allows to break requirement for total order" | ||
| 24437 | " of dirty pages, when they are added to flush lists.", | ||
| 24438 | NULL, NULL, INNODB_LOG_RECENT_CLOSED_SIZE_DEFAULT, | ||
| 24439 | INNODB_LOG_RECENT_CLOSED_SIZE_MIN, INNODB_LOG_RECENT_CLOSED_SIZE_MAX, 0); | ||
| 24440 | |||
| 24441 | static MYSQL_SYSVAR_ULONG( | ||
| 24442 | log_wait_for_write_spin_delay, srv_log_wait_for_write_spin_delay, | ||
| 24443 | PLUGIN_VAR_RQCMDARG, | ||
| 24444 | "Number of spin iterations, when spinning and waiting for log buffer" | ||
| 24445 | " written up to given LSN, before we fallback to loop with sleeps." | ||
| 24446 | " This is not used when user thread has to wait for log flushed to disk.", | ||
| 24447 | NULL, NULL, INNODB_LOG_WAIT_FOR_WRITE_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24448 | |||
| 24449 | extern ulong srv_log_wait_for_write_timeout; | ||
| 24450 | static MYSQL_SYSVAR_ULONG( | ||
| 24451 | log_wait_for_write_timeout, srv_log_wait_for_write_timeout, | ||
| 24452 | PLUGIN_VAR_RQCMDARG, | ||
| 24453 | "Timeout used when waiting for redo write (microseconds).", NULL, NULL, | ||
| 24454 | INNODB_LOG_WAIT_FOR_WRITE_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24455 | |||
| 24456 | static MYSQL_SYSVAR_ULONG( | ||
| 24457 | log_wait_for_flush_spin_delay, srv_log_wait_for_flush_spin_delay, | ||
| 24458 | PLUGIN_VAR_RQCMDARG, | ||
| 24459 | "Number of spin iterations, when spinning and waiting for log flushed.", | ||
| 24460 | NULL, NULL, INNODB_LOG_WAIT_FOR_FLUSH_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24461 | |||
| 24462 | extern ulong srv_log_wait_for_flush_timeout; | ||
| 24463 | static MYSQL_SYSVAR_ULONG( | ||
| 24464 | log_wait_for_flush_timeout, srv_log_wait_for_flush_timeout, | ||
| 24465 | PLUGIN_VAR_RQCMDARG, | ||
| 24466 | "Timeout used when waiting for redo flush (microseconds).", NULL, NULL, | ||
| 24467 | INNODB_LOG_WAIT_FOR_FLUSH_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24468 | |||
| 24469 | static MYSQL_SYSVAR_ULONG( | ||
| 24470 | log_write_max_size, srv_log_write_max_size, PLUGIN_VAR_RQCMDARG, | ||
| 24471 | "Size available for next write, which satisfies log_writer thread" | ||
| 24472 | " when it follows links in recent written buffer.", | ||
| 24473 | NULL, NULL, INNODB_LOG_WRITE_MAX_SIZE_DEFAULT, 0, ULONG_MAX, | ||
| 24474 | OS_FILE_LOG_BLOCK_SIZE); | ||
| 24475 | |||
| 24476 | static MYSQL_SYSVAR_ULONG( | ||
| 24477 | log_writer_spin_delay, srv_log_writer_spin_delay, PLUGIN_VAR_RQCMDARG, | ||
| 24478 | "Number of spin iterations, for which log writer thread is waiting" | ||
| 24479 | " for new data to write without sleeping.", | ||
| 24480 | NULL, NULL, INNODB_LOG_WRITER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24481 | |||
| 24482 | extern ulong srv_log_writer_timeout; | ||
| 24483 | static MYSQL_SYSVAR_ULONG( | ||
| 24484 | log_writer_timeout, srv_log_writer_timeout, PLUGIN_VAR_RQCMDARG, | ||
| 24485 | "Initial timeout used to wait on event in log writer thread (microseconds)", | ||
| 24486 | NULL, NULL, INNODB_LOG_WRITER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24487 | |||
| 24488 | extern ulong srv_log_checkpoint_every; | ||
| 24489 | static MYSQL_SYSVAR_ULONG( | ||
| 24490 | log_checkpoint_every, srv_log_checkpoint_every, PLUGIN_VAR_RQCMDARG, | ||
| 24491 | "Checkpoints are executed at least every that many milliseconds.", NULL, | ||
| 24492 | NULL, INNODB_LOG_CHECKPOINT_EVERY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24493 | |||
| 24494 | static MYSQL_SYSVAR_ULONG( | ||
| 24495 | log_flusher_spin_delay, srv_log_flusher_spin_delay, PLUGIN_VAR_RQCMDARG, | ||
| 24496 | "Number of spin iterations, for which log flusher thread is waiting" | ||
| 24497 | " for new data to flush, without sleeping.", | ||
| 24498 | NULL, NULL, INNODB_LOG_FLUSHER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24499 | |||
| 24500 | extern ulong srv_log_flusher_timeout; | ||
| 24501 | static MYSQL_SYSVAR_ULONG(log_flusher_timeout, srv_log_flusher_timeout, | ||
| 24502 | PLUGIN_VAR_RQCMDARG, | ||
| 24503 | "Initial timeout used to wait on event in log " | ||
| 24504 | "flusher thread (microseconds)", | ||
| 24505 | NULL, NULL, INNODB_LOG_FLUSHER_TIMEOUT_DEFAULT, 0, | ||
| 24506 | ULONG_MAX, 0); | ||
| 24507 | |||
| 24508 | static MYSQL_SYSVAR_ULONG( | ||
| 24509 | log_write_notifier_spin_delay, srv_log_write_notifier_spin_delay, | ||
| 24510 | PLUGIN_VAR_RQCMDARG, | ||
| 24511 | "Number of spin iterations, for which log write notifier thread is waiting" | ||
| 24512 | " for advanced write_lsn, without sleeping.", | ||
| 24513 | NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24514 | |||
| 24515 | extern ulong srv_log_write_notifier_timeout; | ||
| 24516 | static MYSQL_SYSVAR_ULONG( | ||
| 24517 | log_write_notifier_timeout, srv_log_write_notifier_timeout, | ||
| 24518 | PLUGIN_VAR_RQCMDARG, | ||
| 24519 | "Initial timeout used to wait on event in log write notifier thread" | ||
| 24520 | " (microseconds)", | ||
| 24521 | NULL, NULL, INNODB_LOG_WRITE_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24522 | |||
| 24523 | static MYSQL_SYSVAR_ULONG( | ||
| 24524 | log_flush_notifier_spin_delay, srv_log_flush_notifier_spin_delay, | ||
| 24525 | PLUGIN_VAR_RQCMDARG, | ||
| 24526 | "Number of spin iterations, for which log flush notifier thread is waiting" | ||
| 24527 | " for advanced flushed_to_disk_lsn, without sleeping.", | ||
| 24528 | NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_SPIN_DELAY_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24529 | |||
| 24530 | extern ulong srv_log_flush_notifier_timeout; | ||
| 24531 | static MYSQL_SYSVAR_ULONG( | ||
| 24532 | log_flush_notifier_timeout, srv_log_flush_notifier_timeout, | ||
| 24533 | PLUGIN_VAR_RQCMDARG, | ||
| 24534 | "Initial timeout used to wait on event in log flush notifier thread" | ||
| 24535 | " (microseconds)", | ||
| 24536 | NULL, NULL, INNODB_LOG_FLUSH_NOTIFIER_TIMEOUT_DEFAULT, 0, ULONG_MAX, 0); | ||
| 24537 | |||
| 24538 | #endif /* ENABLE_EXPERIMENT_SYSVARS */ | ||
| 24539 | |||
| 24540 | static MYSQL_SYSVAR_UINT( | ||
| 24541 | old_blocks_pct, innobase_old_blocks_pct, PLUGIN_VAR_RQCMDARG, | ||
| 24542 | "Percentage of the buffer pool to reserve for 'old' blocks.", nullptr, | ||
| 24543 | innodb_old_blocks_pct_update, 100 * 3 / 8, 5, 95, 0); | ||
| 24544 | |||
| 24545 | extern uint buf_LRU_old_threshold; | ||
| 24546 | static MYSQL_SYSVAR_UINT( | ||
| 24547 | old_blocks_time, buf_LRU_old_threshold, PLUGIN_VAR_RQCMDARG, | ||
| 24548 | "Move blocks to the 'new' end of the buffer pool if the first access" | ||
| 24549 | " was at least this many milliseconds ago." | ||
| 24550 | " The timeout is disabled if 0.", | ||
| 24551 | nullptr, nullptr, 1000, 0, UINT_MAX32, 0); | ||
| 24552 | |||
| 24553 | static MYSQL_SYSVAR_LONG( | ||
| 24554 | open_files, innobase_open_files, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24555 | "How many files at the maximum InnoDB keeps open at the same time.", | ||
| 24556 | nullptr, nullptr, 0L, 0L, LONG_MAX, 0); | ||
| 24557 | |||
| 24558 | static MYSQL_SYSVAR_ULONG( | ||
| 24559 | sync_spin_loops, srv_n_spin_wait_rounds, PLUGIN_VAR_RQCMDARG, | ||
| 24560 | "Count of spin-loop rounds in InnoDB mutexes (30 by default)", nullptr, | ||
| 24561 | nullptr, 30L, 0L, ~0UL, 0); | ||
| 24562 | |||
| 24563 | static MYSQL_SYSVAR_ULONG( | ||
| 24564 | spin_wait_delay, srv_spin_wait_delay, PLUGIN_VAR_OPCMDARG, | ||
| 24565 | "Maximum delay between polling for a spin lock (6 by default)", nullptr, | ||
| 24566 | nullptr, 6L, 0L, 1000, 0); | ||
| 24567 | |||
| 24568 | static MYSQL_SYSVAR_ULONG(spin_wait_pause_multiplier, | ||
| 24569 | ut::spin_wait_pause_multiplier, PLUGIN_VAR_RQCMDARG, | ||
| 24570 | "Controls how many times in a row to use a PAUSE " | ||
| 24571 | "instruction to achieve one unit of delay in a spin " | ||
| 24572 | "lock (see @@innodb_spin_wait_delay), defaults to 50", | ||
| 24573 | nullptr, nullptr, 50, 0, 100, 0); | ||
| 24574 | |||
| 24575 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 24576 | fsync_threshold, os_fsync_threshold, PLUGIN_VAR_RQCMDARG, | ||
| 24577 | "The value of this variable determines how often InnoDB calls fsync when " | ||
| 24578 | "creating a new file. Default is zero which would make InnoDB flush the " | ||
| 24579 | "entire file at once before closing it.", | ||
| 24580 | nullptr, nullptr, 0, 0, ~0ULL, UNIV_PAGE_SIZE); | ||
| 24581 | |||
| 24582 | static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency, | ||
| 24583 | PLUGIN_VAR_RQCMDARG, | ||
| 24584 | "Helps in performance tuning in heavily concurrent " | ||
| 24585 | "environments. Sets the maximum number of threads " | ||
| 24586 | "allowed inside InnoDB. Value 0 will disable the " | ||
| 24587 | "thread throttling.", | ||
| 24588 | nullptr, innodb_thread_concurrency_update, 0, 0, 1000, | ||
| 24589 | 0); | ||
| 24590 | |||
| 24591 | static MYSQL_SYSVAR_ULONG( | ||
| 24592 | adaptive_max_sleep_delay, srv_adaptive_max_sleep_delay, PLUGIN_VAR_RQCMDARG, | ||
| 24593 | "The upper limit of the sleep delay in usec. Value of 0 disables it.", | ||
| 24594 | nullptr, nullptr, 150000, /* Default setting */ | ||
| 24595 | 0, /* Minimum value */ | ||
| 24596 | 1000000, 0); /* Maximum value */ | ||
| 24597 | |||
| 24598 | static MYSQL_SYSVAR_ULONG( | ||
| 24599 | thread_sleep_delay, srv_thread_sleep_delay, PLUGIN_VAR_RQCMDARG, | ||
| 24600 | "Time of innodb thread sleeping before joining InnoDB queue (usec)." | ||
| 24601 | " Value 0 disable a sleep", | ||
| 24602 | nullptr, nullptr, 10000L, 0L, 1000000L, 0); | ||
| 24603 | |||
| 24604 | static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path, | ||
| 24605 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 24606 | PLUGIN_VAR_NOPERSIST, | ||
| 24607 | "Path to individual files and their sizes.", nullptr, | ||
| 24608 | nullptr, (char *)"ibdata1:12M:autoextend"); | ||
| 24609 | |||
| 24610 | static MYSQL_SYSVAR_STR(temp_data_file_path, innobase_temp_data_file_path, | ||
| 24611 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 24612 | PLUGIN_VAR_NOPERSIST, | ||
| 24613 | "Path to files and their sizes making temp-tablespace.", | ||
| 24614 | nullptr, nullptr, (char *)"ibtmp1:12M:autoextend"); | ||
| 24615 | |||
| 24616 | static MYSQL_SYSVAR_BOOL( | ||
| 24617 | temp_tablespace_encrypt, srv_tmp_tablespace_encrypt, PLUGIN_VAR_OPCMDARG, | ||
| 24618 | "Enable or disable encryption of temporary tablespace.", nullptr, | ||
| 24619 | innodb_temp_tablespace_encryption_update, false); | ||
| 24620 | |||
| 24621 | static MYSQL_SYSVAR_ENUM( | ||
| 24622 | sys_tablespace_encrypt, srv_sys_tablespace_encrypt, | ||
| 24623 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 24624 | "Enable this option at bootstrap to encrypt system tablespace." | ||
| 24625 | "Set it to RE_ENCRYPTING_TO_KEYRING to allow re-encryption to KEYRING.", | ||
| 24626 | innodb_sys_tablespace_encyption_validate, nullptr, | ||
| 24627 | SYS_TABLESPACE_ENCRYPT_OFF, &sys_tablespace_encrypt_typelib); | ||
| 24628 | |||
| 24629 | static MYSQL_SYSVAR_STR( | ||
| 24630 | undo_directory, srv_undo_dir, | ||
| 24631 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 24632 | "Directory where undo tablespace files live, this path can be absolute.", | ||
| 24633 | nullptr, nullptr, nullptr); | ||
| 24634 | |||
| 24635 | static MYSQL_SYSVAR_STR( | ||
| 24636 | temp_tablespaces_dir, ibt::srv_temp_dir, | ||
| 24637 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 24638 | "Directory where temp tablespace files live, this path can be absolute.", | ||
| 24639 | nullptr, nullptr, nullptr); | ||
| 24640 | |||
| 24641 | static MYSQL_SYSVAR_ULONG(undo_tablespaces, srv_undo_tablespaces, | ||
| 24642 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 24643 | "Number of undo tablespaces to use. (deprecated)", | ||
| 24644 | nullptr, innodb_undo_tablespaces_update, | ||
| 24645 | FSP_IMPLICIT_UNDO_TABLESPACES, /* Default seting */ | ||
| 24646 | FSP_MIN_UNDO_TABLESPACES, /* Minimum value */ | ||
| 24647 | FSP_MAX_UNDO_TABLESPACES, 0); /* Maximum value */ | ||
| 24648 | |||
| 24649 | static MYSQL_SYSVAR_ULONGLONG( | ||
| 24650 | max_undo_log_size, srv_max_undo_tablespace_size, PLUGIN_VAR_OPCMDARG, | ||
| 24651 | "Maximum size of an UNDO tablespace in MB (If an UNDO tablespace grows" | ||
| 24652 | " beyond this size it will be truncated in due course). ", | ||
| 24653 | nullptr, nullptr, 1024 * 1024 * 1024L, 10 * 1024 * 1024L, ~0ULL, 0); | ||
| 24654 | |||
| 24655 | static MYSQL_SYSVAR_ULONG( | ||
| 24656 | purge_rseg_truncate_frequency, srv_purge_rseg_truncate_frequency, | ||
| 24657 | PLUGIN_VAR_OPCMDARG, | ||
| 24658 | "Dictates rate at which UNDO records are purged. Value N means" | ||
| 24659 | " purge rollback segment(s) on every Nth iteration of purge invocation", | ||
| 24660 | nullptr, nullptr, 128, 1, 128, 0); | ||
| 24661 | |||
| 24662 | static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate, | ||
| 24663 | PLUGIN_VAR_OPCMDARG, | ||
| 24664 | "Enable or Disable Truncate of UNDO tablespace.", | ||
| 24665 | nullptr, nullptr, true); | ||
| 24666 | |||
| 24667 | /* This is the number of rollback segments per undo tablespace. | ||
| 24668 | This applies to the temporary tablespace, the system tablespace, | ||
| 24669 | and all undo tablespaces. */ | ||
| 24670 | static MYSQL_SYSVAR_ULONG( | ||
| 24671 | rollback_segments, srv_rollback_segments, PLUGIN_VAR_OPCMDARG, | ||
| 24672 | "Number of rollback segments per tablespace. This applies to the system" | ||
| 24673 | " tablespace, the temporary tablespace & any undo tablespace.", | ||
| 24674 | nullptr, innodb_rollback_segments_update, | ||
| 24675 | FSP_MAX_ROLLBACK_SEGMENTS, /* Default setting */ | ||
| 24676 | 1, /* Minimum value */ | ||
| 24677 | FSP_MAX_ROLLBACK_SEGMENTS, 0); /* Maximum value */ | ||
| 24678 | |||
| 24679 | static MYSQL_SYSVAR_BOOL(undo_log_encrypt, srv_undo_log_encrypt, | ||
| 24680 | PLUGIN_VAR_OPCMDARG, | ||
| 24681 | "Enable or disable Encrypt of UNDO tablespace.", | ||
| 24682 | validate_innodb_undo_log_encrypt, nullptr, false); | ||
| 24683 | |||
| 24684 | static MYSQL_SYSVAR_LONG( | ||
| 24685 | autoinc_lock_mode, innobase_autoinc_lock_mode, | ||
| 24686 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, | ||
| 24687 | "The AUTOINC lock modes supported by InnoDB:" | ||
| 24688 | " 0 => Old style AUTOINC locking (for backward compatibility);" | ||
| 24689 | " 1 => New style AUTOINC locking;" | ||
| 24690 | " 2 => No AUTOINC locking (unsafe for SBR)", | ||
| 24691 | nullptr, nullptr, AUTOINC_NO_LOCKING, /* Default setting */ | ||
| 24692 | AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */ | ||
| 24693 | AUTOINC_NO_LOCKING, 0); /* Maximum value */ | ||
| 24694 | |||
| 24695 | static MYSQL_SYSVAR_STR(version, innodb_version_str, | ||
| 24696 | PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY | | ||
| 24697 | PLUGIN_VAR_NOPERSIST, | ||
| 24698 | "InnoDB version", nullptr, nullptr, INNODB_VERSION_STR); | ||
| 24699 | |||
| 24700 | static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio, | ||
| 24701 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 24702 | "Use native AIO if supported on this platform.", | ||
| 24703 | nullptr, nullptr, true); | ||
| 24704 | |||
| 24705 | #ifdef HAVE_LIBNUMA | ||
| 24706 | static MYSQL_SYSVAR_BOOL( | ||
| 24707 | numa_interleave, srv_numa_interleave, | ||
| 24708 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 24709 | "Use NUMA interleave memory policy to allocate InnoDB buffer pool.", | ||
| 24710 | nullptr, nullptr, false); | ||
| 24711 | #endif /* HAVE_LIBNUMA */ | ||
| 24712 | |||
| 24713 | static MYSQL_SYSVAR_BOOL( | ||
| 24714 | api_enable_binlog, ib_binlog_enabled, | ||
| 24715 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 24716 | "Enable binlog for applications direct access InnoDB through InnoDB APIs", | ||
| 24717 | nullptr, nullptr, false); | ||
| 24718 | |||
| 24719 | static MYSQL_SYSVAR_BOOL( | ||
| 24720 | api_enable_mdl, ib_mdl_enabled, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 24721 | "Enable MDL for applications direct access InnoDB through InnoDB APIs", | ||
| 24722 | nullptr, nullptr, false); | ||
| 24723 | |||
| 24724 | static MYSQL_SYSVAR_BOOL( | ||
| 24725 | api_disable_rowlock, ib_disable_row_lock, | ||
| 24726 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 24727 | "Disable row lock when direct access InnoDB through InnoDB APIs", nullptr, | ||
| 24728 | nullptr, false); | ||
| 24729 | |||
| 24730 | static MYSQL_SYSVAR_ULONG(api_trx_level, ib_trx_level_setting, | ||
| 24731 | PLUGIN_VAR_OPCMDARG, | ||
| 24732 | "InnoDB API transaction isolation level", nullptr, | ||
| 24733 | nullptr, 0, /* Default setting */ | ||
| 24734 | 0, /* Minimum value */ | ||
| 24735 | 3, 0); /* Maximum value */ | ||
| 24736 | |||
| 24737 | static MYSQL_SYSVAR_ULONG(api_bk_commit_interval, ib_bk_commit_interval, | ||
| 24738 | PLUGIN_VAR_OPCMDARG, | ||
| 24739 | "Background commit interval in seconds", nullptr, | ||
| 24740 | nullptr, 5, /* Default setting */ | ||
| 24741 | 1, /* Minimum value */ | ||
| 24742 | 1024 * 1024 * 1024, 0); /* Maximum value */ | ||
| 24743 | |||
| 24744 | static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering, | ||
| 24745 | PLUGIN_VAR_RQCMDARG, | ||
| 24746 | "Buffer changes to reduce random access:" | ||
| 24747 | " OFF, ON, inserting, deleting, changing, or purging.", | ||
| 24748 | nullptr, nullptr, IBUF_USE_ALL, | ||
| 24749 | &innodb_change_buffering_typelib); | ||
| 24750 | |||
| 24751 | static MYSQL_SYSVAR_UINT( | ||
| 24752 | change_buffer_max_size, srv_change_buffer_max_size, PLUGIN_VAR_RQCMDARG, | ||
| 24753 | "Maximum on-disk size of change buffer in terms of percentage" | ||
| 24754 | " of the buffer pool.", | ||
| 24755 | nullptr, innodb_change_buffer_max_size_update, CHANGE_BUFFER_DEFAULT_SIZE, | ||
| 24756 | 0, 50, 0); | ||
| 24757 | |||
| 24758 | static MYSQL_SYSVAR_ENUM( | ||
| 24759 | stats_method, srv_innodb_stats_method, PLUGIN_VAR_RQCMDARG, | ||
| 24760 | "Specifies how InnoDB index statistics collection code should" | ||
| 24761 | " treat NULLs. Possible values are NULLS_EQUAL (default)," | ||
| 24762 | " NULLS_UNEQUAL and NULLS_IGNORED", | ||
| 24763 | nullptr, nullptr, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib); | ||
| 24764 | |||
| 24765 | #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG | ||
| 24766 | static MYSQL_SYSVAR_UINT( | ||
| 24767 | change_buffering_debug, ibuf_debug, PLUGIN_VAR_RQCMDARG, | ||
| 24768 | "Debug flags for InnoDB change buffering (0=none, 2=crash at merge)", | ||
| 24769 | nullptr, nullptr, 0, 0, 2, 0); | ||
| 24770 | |||
| 24771 | static MYSQL_SYSVAR_BOOL(disable_background_merge, | ||
| 24772 | srv_ibuf_disable_background_merge, | ||
| 24773 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_RQCMDARG, | ||
| 24774 | "Disable change buffering merges by the master thread", | ||
| 24775 | nullptr, nullptr, false); | ||
| 24776 | |||
| 24777 | static MYSQL_SYSVAR_ENUM( | ||
| 24778 | compress_debug, srv_debug_compress, PLUGIN_VAR_RQCMDARG, | ||
| 24779 | "Compress all tables, without specifying the COMPRESS table attribute", | ||
| 24780 | nullptr, nullptr, Compression::NONE, &innodb_debug_compress_typelib); | ||
| 24781 | #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ | ||
| 24782 | |||
| 24783 | static MYSQL_SYSVAR_BOOL( | ||
| 24784 | random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG, | ||
| 24785 | "Whether to use read ahead for random access within an extent.", nullptr, | ||
| 24786 | nullptr, false); | ||
| 24787 | |||
| 24788 | static MYSQL_SYSVAR_ULONG( | ||
| 24789 | read_ahead_threshold, srv_read_ahead_threshold, PLUGIN_VAR_RQCMDARG, | ||
| 24790 | "Number of pages that must be accessed sequentially for InnoDB to" | ||
| 24791 | " trigger a readahead.", | ||
| 24792 | nullptr, nullptr, 56, 0, 64, 0); | ||
| 24793 | |||
| 24794 | static MYSQL_SYSVAR_STR(monitor_enable, innobase_enable_monitor_counter, | ||
| 24795 | PLUGIN_VAR_RQCMDARG, "Turn on a monitor counter", | ||
| 24796 | innodb_monitor_validate, innodb_enable_monitor_update, | ||
| 24797 | nullptr); | ||
| 24798 | |||
| 24799 | static MYSQL_SYSVAR_STR(monitor_disable, innobase_disable_monitor_counter, | ||
| 24800 | PLUGIN_VAR_RQCMDARG, "Turn off a monitor counter", | ||
| 24801 | innodb_monitor_validate, innodb_disable_monitor_update, | ||
| 24802 | nullptr); | ||
| 24803 | |||
| 24804 | static MYSQL_SYSVAR_STR(monitor_reset, innobase_reset_monitor_counter, | ||
| 24805 | PLUGIN_VAR_RQCMDARG, "Reset a monitor counter", | ||
| 24806 | innodb_monitor_validate, innodb_reset_monitor_update, | ||
| 24807 | nullptr); | ||
| 24808 | |||
| 24809 | static MYSQL_SYSVAR_STR(monitor_reset_all, innobase_reset_all_monitor_counter, | ||
| 24810 | PLUGIN_VAR_RQCMDARG, | ||
| 24811 | "Reset all values for a monitor counter", | ||
| 24812 | innodb_monitor_validate, | ||
| 24813 | innodb_reset_all_monitor_update, nullptr); | ||
| 24814 | |||
| 24815 | static MYSQL_SYSVAR_BOOL(status_output, srv_print_innodb_monitor, | ||
| 24816 | PLUGIN_VAR_OPCMDARG, | ||
| 24817 | "Enable InnoDB monitor output to the error log.", | ||
| 24818 | nullptr, nullptr, false); | ||
| 24819 | |||
| 24820 | static MYSQL_SYSVAR_BOOL(status_output_locks, srv_print_innodb_lock_monitor, | ||
| 24821 | PLUGIN_VAR_OPCMDARG, | ||
| 24822 | "Enable InnoDB lock monitor output to the error log." | ||
| 24823 | " Requires innodb_status_output=ON.", | ||
| 24824 | nullptr, nullptr, false); | ||
| 24825 | |||
| 24826 | static MYSQL_SYSVAR_BOOL( | ||
| 24827 | print_all_deadlocks, srv_print_all_deadlocks, PLUGIN_VAR_OPCMDARG, | ||
| 24828 | "Print all deadlocks to MySQL error log (off by default)", nullptr, nullptr, | ||
| 24829 | false); | ||
| 24830 | |||
| 24831 | static MYSQL_SYSVAR_BOOL( | ||
| 24832 | print_lock_wait_timeout_info, srv_print_lock_wait_timeout_info, | ||
| 24833 | PLUGIN_VAR_OPCMDARG, | ||
| 24834 | "Print lock wait timeout info to MySQL error log (off by default)", nullptr, | ||
| 24835 | nullptr, false); | ||
| 24836 | |||
| 24837 | static MYSQL_SYSVAR_ULONG( | ||
| 24838 | compression_failure_threshold_pct, zip_failure_threshold_pct, | ||
| 24839 | PLUGIN_VAR_OPCMDARG, | ||
| 24840 | "If the compression failure rate of a table is greater than this number" | ||
| 24841 | " more padding is added to the pages to reduce the failures. A value of" | ||
| 24842 | " zero implies no padding", | ||
| 24843 | nullptr, nullptr, 5, 0, 100, 0); | ||
| 24844 | |||
| 24845 | static MYSQL_SYSVAR_ULONG( | ||
| 24846 | compression_pad_pct_max, zip_pad_max, PLUGIN_VAR_OPCMDARG, | ||
| 24847 | "Percentage of empty space on a data page that can be reserved" | ||
| 24848 | " to make the page compressible.", | ||
| 24849 | nullptr, nullptr, 50, 0, 75, 0); | ||
| 24850 | |||
| 24851 | static MYSQL_SYSVAR_BOOL(read_only, srv_read_only_mode, | ||
| 24852 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY | | ||
| 24853 | PLUGIN_VAR_NOPERSIST, | ||
| 24854 | "Start InnoDB in read only mode (off by default)", | ||
| 24855 | nullptr, nullptr, false); | ||
| 24856 | |||
| 24857 | static MYSQL_SYSVAR_BOOL( | ||
| 24858 | cmp_per_index_enabled, srv_cmp_per_index_enabled, PLUGIN_VAR_OPCMDARG, | ||
| 24859 | "Enable INFORMATION_SCHEMA.innodb_cmp_per_index," | ||
| 24860 | " may have negative impact on performance (off by default)", | ||
| 24861 | nullptr, innodb_cmp_per_index_update, false); | ||
| 24862 | |||
| 24863 | static MYSQL_SYSVAR_ENUM( | ||
| 24864 | default_row_format, innodb_default_row_format, PLUGIN_VAR_RQCMDARG, | ||
| 24865 | "The default ROW FORMAT for all innodb tables created without explicit" | ||
| 24866 | " ROW_FORMAT. Possible values are REDUNDANT, COMPACT, and DYNAMIC." | ||
| 24867 | " The ROW_FORMAT value COMPRESSED is not allowed", | ||
| 24868 | nullptr, nullptr, DEFAULT_ROW_FORMAT_DYNAMIC, | ||
| 24869 | &innodb_default_row_format_typelib); | ||
| 24870 | |||
| 24871 | static MYSQL_SYSVAR_STR( | ||
| 24872 | redo_log_archive_dirs, meb::redo_log_archive_dirs, | ||
| 24873 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, | ||
| 24874 | "Limit the location of the redo log archive to the semicolon " | ||
| 24875 | "separated list of labeled directories", | ||
| 24876 | /*validate_func*/ meb::validate_redo_log_archive_dirs, | ||
| 24877 | /*update_func*/ nullptr, /*default*/ nullptr); | ||
| 24878 | |||
| 24879 | static MYSQL_SYSVAR_BOOL(redo_log_encrypt, srv_redo_log_encrypt, | ||
| 24880 | PLUGIN_VAR_OPCMDARG, | ||
| 24881 | "Enable or disable Encryption of REDO tablespace.", | ||
| 24882 | validate_innodb_redo_log_encrypt, nullptr, false); | ||
| 24883 | |||
| 24884 | static MYSQL_SYSVAR_BOOL( | ||
| 24885 | print_ddl_logs, srv_print_ddl_logs, PLUGIN_VAR_OPCMDARG, | ||
| 24886 | "Print all DDl logs to MySQL error log (off by default)", nullptr, nullptr, | ||
| 24887 | false); | ||
| 24888 | |||
| 24889 | #ifdef UNIV_DEBUG | ||
| 24890 | static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug, | ||
| 24891 | PLUGIN_VAR_RQCMDARG, | ||
| 24892 | "Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for " | ||
| 24893 | "trx_rsegf_undo_find_free()", | ||
| 24894 | nullptr, nullptr, 0, 0, 1024, 0); | ||
| 24895 | |||
| 24896 | static MYSQL_SYSVAR_UINT( | ||
| 24897 | limit_optimistic_insert_debug, btr_cur_limit_optimistic_insert_debug, | ||
| 24898 | PLUGIN_VAR_RQCMDARG, | ||
| 24899 | "Artificially limit the number of records per B-tree page (0=unlimited).", | ||
| 24900 | nullptr, nullptr, 0, 0, UINT_MAX32, 0); | ||
| 24901 | |||
| 24902 | static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug, | ||
| 24903 | srv_purge_view_update_only_debug, PLUGIN_VAR_NOCMDARG, | ||
| 24904 | "Pause actual purging any delete-marked records, but " | ||
| 24905 | "merely update the purge view." | ||
| 24906 | " It is to create artificially the situation the " | ||
| 24907 | "purge view have been updated" | ||
| 24908 | " but the each purges were not done yet.", | ||
| 24909 | nullptr, nullptr, false); | ||
| 24910 | // clang-format off | ||
| 24911 | static MYSQL_SYSVAR_ULONG( | ||
| 24912 | fil_make_page_dirty_debug, | ||
| 24913 | srv_fil_make_page_dirty_debug, PLUGIN_VAR_OPCMDARG, | ||
| 24914 | "Make the first page of the given tablespace dirty.", | ||
| 24915 | nullptr, innodb_make_page_dirty, UINT_MAX32, 0, UINT_MAX32, 0); | ||
| 24916 | // clang-format on | ||
| 24917 | |||
| 24918 | static MYSQL_SYSVAR_ULONG(saved_page_number_debug, srv_saved_page_number_debug, | ||
| 24919 | PLUGIN_VAR_OPCMDARG, "An InnoDB page number.", | ||
| 24920 | nullptr, innodb_save_page_no, 0, 0, UINT_MAX32, 0); | ||
| 24921 | |||
| 24922 | static MYSQL_SYSVAR_BOOL(page_cleaner_disabled_debug, | ||
| 24923 | innodb_page_cleaner_disabled_debug, | ||
| 24924 | PLUGIN_VAR_OPCMDARG, "Disable page cleaner", nullptr, | ||
| 24925 | buf_flush_page_cleaner_disabled_debug_update, false); | ||
| 24926 | |||
| 24927 | static MYSQL_SYSVAR_BOOL(dict_stats_disabled_debug, | ||
| 24928 | innodb_dict_stats_disabled_debug, PLUGIN_VAR_OPCMDARG, | ||
| 24929 | "Disable dict_stats thread", nullptr, | ||
| 24930 | dict_stats_disabled_debug_update, false); | ||
| 24931 | |||
| 24932 | static MYSQL_SYSVAR_BOOL(master_thread_disabled_debug, | ||
| 24933 | srv_master_thread_disabled_debug, PLUGIN_VAR_OPCMDARG, | ||
| 24934 | "Disable master thread", nullptr, | ||
| 24935 | srv_master_thread_disabled_debug_update, false); | ||
| 24936 | |||
| 24937 | static MYSQL_SYSVAR_BOOL(sync_debug, srv_sync_debug, | ||
| 24938 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 24939 | "Enable the sync debug checks", nullptr, nullptr, | ||
| 24940 | false); | ||
| 24941 | |||
| 24942 | static MYSQL_SYSVAR_BOOL(buffer_pool_debug, srv_buf_pool_debug, | ||
| 24943 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, | ||
| 24944 | "Enable buffer pool debug", nullptr, nullptr, false); | ||
| 24945 | |||
| 24946 | static MYSQL_SYSVAR_BOOL(ddl_log_crash_reset_debug, | ||
| 24947 | innodb_ddl_log_crash_reset_debug, PLUGIN_VAR_OPCMDARG, | ||
| 24948 | "Reset all crash injection counters to 1", nullptr, | ||
| 24949 | ddl_log_crash_reset, false); | ||
| 24950 | |||
| 24951 | #endif /* UNIV_DEBUG */ | ||
| 24952 | |||
| 24953 | static MYSQL_SYSVAR_STR(directories, srv_innodb_directories, | ||
| 24954 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | | ||
| 24955 | PLUGIN_VAR_NOPERSIST, | ||
| 24956 | "List of directories 'dir1;dir2;..;dirN' to scan for " | ||
| 24957 | "tablespace files. Default is to scan " | ||
| 24958 | "'innodb-data-home-dir;innodb-undo-directory;datadir'", | ||
| 24959 | nullptr, nullptr, nullptr); | ||
| 24960 | |||
| 24961 | #ifdef UNIV_DEBUG | ||
| 24962 | /** Use this variable innodb_interpreter to execute debug code within InnoDB. | ||
| 24963 | The output is stored in the innodb_interpreter_output variable. */ | ||
| 24964 | static MYSQL_THDVAR_STR(interpreter, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 24965 | "Invoke InnoDB test interpreter with commands" | ||
| 24966 | " to be executed.", | ||
| 24967 | ib_interpreter_check, ib_interpreter_update, "init"); | ||
| 24968 | |||
| 24969 | /** When testing commands are executed in the innodb_interpreter variable, the | ||
| 24970 | output is stored in this innodb_interpreter_output variable. */ | ||
| 24971 | static MYSQL_THDVAR_STR(interpreter_output, | ||
| 24972 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC | | ||
| 24973 | PLUGIN_VAR_NOPERSIST, | ||
| 24974 | "Output from InnoDB testing module (ut0test).", nullptr, | ||
| 24975 | nullptr, "The Default Value"); | ||
| 24976 | |||
| 24977 | 54 | char **thd_innodb_interpreter_output(THD *thd) { | |
| 24978 | return (MYSQL_SYSVAR_NAME(interpreter_output) | ||
| 24979 | 54 | .resolve(thd, MYSQL_SYSVAR_NAME(interpreter_output).offset)); | |
| 24980 | } | ||
| 24981 | |||
| 24982 | 54 | char **thd_innodb_interpreter(THD *thd) { | |
| 24983 | return MYSQL_SYSVAR_NAME(interpreter) | ||
| 24984 | 54 | .resolve(thd, MYSQL_SYSVAR_NAME(interpreter).offset); | |
| 24985 | } | ||
| 24986 | #endif /* UNIV_DEBUG */ | ||
| 24987 | |||
| 24988 | static const char *corrupt_table_action_names[] = {"assert", /* 0 */ | ||
| 24989 | "warn", /* 1 */ | ||
| 24990 | "salvage", /* 2 */ | ||
| 24991 | NullS}; | ||
| 24992 | |||
| 24993 | static TYPELIB corrupt_table_action_typelib = { | ||
| 24994 | array_elements(corrupt_table_action_names) - 1, | ||
| 24995 | "corrupt_table_action_typelib", corrupt_table_action_names, nullptr}; | ||
| 24996 | |||
| 24997 | static MYSQL_SYSVAR_ENUM( | ||
| 24998 | corrupt_table_action, srv_pass_corrupt_table, PLUGIN_VAR_RQCMDARG, | ||
| 24999 | "Warn corruptions of user tables as 'corrupt table' instead of not " | ||
| 25000 | "crashing itself, " | ||
| 25001 | "when used with file_per_table. " | ||
| 25002 | "All file io for the datafile after detected as corrupt are disabled, " | ||
| 25003 | "except for the deletion.", | ||
| 25004 | nullptr, nullptr, 0, &corrupt_table_action_typelib); | ||
| 25005 | |||
| 25006 | static MYSQL_SYSVAR_STR( | ||
| 25007 | parallel_doublewrite_path, srv_parallel_doublewrite_path_deprecated, | ||
| 25008 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOPERSIST, | ||
| 25009 | "Deprecated Percona-specific variable that was used to set path to the " | ||
| 25010 | "parallel doublewrite file and has no effect now. " | ||
| 25011 | "Use --innodb-doublewrite-dir instead.", | ||
| 25012 | nullptr, innodb_parallel_doublewrite_path_update, "xb_doublewrite"); | ||
| 25013 | |||
| 25014 | static MYSQL_SYSVAR_BOOL( | ||
| 25015 | parallel_dblwr_encrypt, srv_parallel_dblwr_encrypt_deprecated, | ||
| 25016 | PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOPERSIST, | ||
| 25017 | "Deprecated Percona-specific variable that was used to enable or " | ||
| 25018 | "disable encryption of parallel doublewrite buffer file and has no " | ||
| 25019 | "effect now.", | ||
| 25020 | nullptr, innodb_parallel_dblwr_encrypt_update, false); | ||
| 25021 | |||
| 25022 | static MYSQL_SYSVAR_UINT( | ||
| 25023 | compressed_columns_zip_level, srv_compressed_columns_zip_level, | ||
| 25024 | PLUGIN_VAR_RQCMDARG, | ||
| 25025 | "Compression level used for compressed columns. 0 is no compression" | ||
| 25026 | ", 1 is fastest and 9 is best compression. Default is 6.", | ||
| 25027 | nullptr, nullptr, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0); | ||
| 25028 | |||
| 25029 | static MYSQL_SYSVAR_ULONG( | ||
| 25030 | compressed_columns_threshold, srv_compressed_columns_threshold, | ||
| 25031 | PLUGIN_VAR_RQCMDARG, | ||
| 25032 | "Compress column data if its length exceeds this value. Default is 96", | ||
| 25033 | nullptr, nullptr, 96, 1, ~0UL, 0); | ||
| 25034 | |||
| 25035 | static MYSQL_SYSVAR_BOOL(encrypt_online_alter_logs, | ||
| 25036 | srv_encrypt_online_alter_logs, | ||
| 25037 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, | ||
| 25038 | "Encrypt online alter logs.", nullptr, nullptr, false); | ||
| 25039 | |||
| 25040 | static MYSQL_SYSVAR_UINT( | ||
| 25041 | encryption_threads, srv_n_fil_crypt_threads_requested, PLUGIN_VAR_RQCMDARG, | ||
| 25042 | "Number of threads performing background key rotation and " | ||
| 25043 | "scrubbing", | ||
| 25044 | innodb_encryption_threads_validate, innodb_encryption_threads_update, 0, 0, | ||
| 25045 | MAX_ENCRYPTION_THREADS, 0); | ||
| 25046 | |||
| 25047 | static MYSQL_SYSVAR_UINT(encryption_rotate_key_age, | ||
| 25048 | srv_fil_crypt_rotate_key_age, PLUGIN_VAR_RQCMDARG, | ||
| 25049 | "Key rotation - re-encrypt in background " | ||
| 25050 | "all pages that were encrypted with a key that " | ||
| 25051 | "many (or more) versions behind. Value 0 indicates " | ||
| 25052 | "that key rotation is disabled.", | ||
| 25053 | NULL, innodb_encryption_rotate_key_age_update, 1, 0, | ||
| 25054 | UINT_MAX32, 0); | ||
| 25055 | |||
| 25056 | static MYSQL_SYSVAR_UINT(encryption_rotation_iops, srv_n_fil_crypt_iops, | ||
| 25057 | PLUGIN_VAR_RQCMDARG, | ||
| 25058 | "Use this many iops for background key rotation", NULL, | ||
| 25059 | innodb_encryption_rotation_iops_update, | ||
| 25060 | srv_n_fil_crypt_iops, 0, UINT_MAX32, 0); | ||
| 25061 | |||
| 25062 | static SYS_VAR *innobase_system_variables[] = { | ||
| 25063 | MYSQL_SYSVAR(api_trx_level), | ||
| 25064 | MYSQL_SYSVAR(api_bk_commit_interval), | ||
| 25065 | MYSQL_SYSVAR(autoextend_increment), | ||
| 25066 | MYSQL_SYSVAR(dedicated_server), | ||
| 25067 | MYSQL_SYSVAR(buffer_pool_size), | ||
| 25068 | MYSQL_SYSVAR(buffer_pool_chunk_size), | ||
| 25069 | MYSQL_SYSVAR(buffer_pool_instances), | ||
| 25070 | MYSQL_SYSVAR(buffer_pool_filename), | ||
| 25071 | MYSQL_SYSVAR(buffer_pool_dump_now), | ||
| 25072 | MYSQL_SYSVAR(buffer_pool_dump_at_shutdown), | ||
| 25073 | MYSQL_SYSVAR(buffer_pool_in_core_file), | ||
| 25074 | MYSQL_SYSVAR(buffer_pool_dump_pct), | ||
| 25075 | #ifdef UNIV_DEBUG | ||
| 25076 | MYSQL_SYSVAR(buffer_pool_evict), | ||
| 25077 | #endif /* UNIV_DEBUG */ | ||
| 25078 | MYSQL_SYSVAR(buffer_pool_load_now), | ||
| 25079 | MYSQL_SYSVAR(buffer_pool_load_abort), | ||
| 25080 | MYSQL_SYSVAR(buffer_pool_load_at_startup), | ||
| 25081 | MYSQL_SYSVAR(lru_scan_depth), | ||
| 25082 | MYSQL_SYSVAR(flush_neighbors), | ||
| 25083 | MYSQL_SYSVAR(checksum_algorithm), | ||
| 25084 | MYSQL_SYSVAR(log_checksums), | ||
| 25085 | MYSQL_SYSVAR(commit_concurrency), | ||
| 25086 | MYSQL_SYSVAR(concurrency_tickets), | ||
| 25087 | MYSQL_SYSVAR(compression_level), | ||
| 25088 | MYSQL_SYSVAR(ddl_buffer_size), | ||
| 25089 | MYSQL_SYSVAR(ddl_threads), | ||
| 25090 | MYSQL_SYSVAR(data_file_path), | ||
| 25091 | MYSQL_SYSVAR(temp_data_file_path), | ||
| 25092 | MYSQL_SYSVAR(temp_tablespace_encrypt), | ||
| 25093 | MYSQL_SYSVAR(sys_tablespace_encrypt), | ||
| 25094 | MYSQL_SYSVAR(data_home_dir), | ||
| 25095 | MYSQL_SYSVAR(extend_and_initialize), | ||
| 25096 | MYSQL_SYSVAR(doublewrite), | ||
| 25097 | MYSQL_SYSVAR(doublewrite_dir), | ||
| 25098 | MYSQL_SYSVAR(doublewrite_batch_size), | ||
| 25099 | MYSQL_SYSVAR(doublewrite_files), | ||
| 25100 | MYSQL_SYSVAR(doublewrite_pages), | ||
| 25101 | MYSQL_SYSVAR(stats_include_delete_marked), | ||
| 25102 | MYSQL_SYSVAR(api_enable_binlog), | ||
| 25103 | MYSQL_SYSVAR(api_enable_mdl), | ||
| 25104 | MYSQL_SYSVAR(api_disable_rowlock), | ||
| 25105 | MYSQL_SYSVAR(fast_shutdown), | ||
| 25106 | MYSQL_SYSVAR(read_io_threads), | ||
| 25107 | MYSQL_SYSVAR(write_io_threads), | ||
| 25108 | MYSQL_SYSVAR(file_per_table), | ||
| 25109 | MYSQL_SYSVAR(flush_log_at_timeout), | ||
| 25110 | MYSQL_SYSVAR(flush_log_at_trx_commit), | ||
| 25111 | MYSQL_SYSVAR(flush_method), | ||
| 25112 | MYSQL_SYSVAR(force_recovery), | ||
| 25113 | #ifdef UNIV_DEBUG | ||
| 25114 | MYSQL_SYSVAR(force_recovery_crash), | ||
| 25115 | #endif /* UNIV_DEBUG */ | ||
| 25116 | MYSQL_SYSVAR(fill_factor), | ||
| 25117 | MYSQL_SYSVAR(ft_cache_size), | ||
| 25118 | MYSQL_SYSVAR(ft_total_cache_size), | ||
| 25119 | MYSQL_SYSVAR(ft_result_cache_limit), | ||
| 25120 | MYSQL_SYSVAR(ft_enable_stopword), | ||
| 25121 | MYSQL_SYSVAR(ft_max_token_size), | ||
| 25122 | MYSQL_SYSVAR(ft_min_token_size), | ||
| 25123 | MYSQL_SYSVAR(ft_num_word_optimize), | ||
| 25124 | MYSQL_SYSVAR(ft_sort_pll_degree), | ||
| 25125 | MYSQL_SYSVAR(force_load_corrupted), | ||
| 25126 | MYSQL_SYSVAR(lock_wait_timeout), | ||
| 25127 | MYSQL_SYSVAR(deadlock_detect), | ||
| 25128 | MYSQL_SYSVAR(page_size), | ||
| 25129 | MYSQL_SYSVAR(log_buffer_size), | ||
| 25130 | MYSQL_SYSVAR(log_file_size), | ||
| 25131 | MYSQL_SYSVAR(log_files_in_group), | ||
| 25132 | MYSQL_SYSVAR(redo_log_capacity), | ||
| 25133 | #ifdef UNIV_DEBUG_DEDICATED | ||
| 25134 | MYSQL_SYSVAR(debug_sys_mem_size), | ||
| 25135 | #endif /* UNIV_DEBUG_DEDICATED */ | ||
| 25136 | MYSQL_SYSVAR(log_write_ahead_size), | ||
| 25137 | MYSQL_SYSVAR(log_group_home_dir), | ||
| 25138 | MYSQL_SYSVAR(log_writer_threads), | ||
| 25139 | MYSQL_SYSVAR(log_spin_cpu_abs_lwm), | ||
| 25140 | MYSQL_SYSVAR(log_spin_cpu_pct_hwm), | ||
| 25141 | MYSQL_SYSVAR(log_wait_for_flush_spin_hwm), | ||
| 25142 | #ifdef ENABLE_EXPERIMENT_SYSVARS | ||
| 25143 | MYSQL_SYSVAR(log_write_events), | ||
| 25144 | MYSQL_SYSVAR(log_flush_events), | ||
| 25145 | MYSQL_SYSVAR(log_recent_written_size), | ||
| 25146 | MYSQL_SYSVAR(log_recent_closed_size), | ||
| 25147 | MYSQL_SYSVAR(log_wait_for_write_spin_delay), | ||
| 25148 | MYSQL_SYSVAR(log_wait_for_write_timeout), | ||
| 25149 | MYSQL_SYSVAR(log_wait_for_flush_spin_delay), | ||
| 25150 | MYSQL_SYSVAR(log_wait_for_flush_timeout), | ||
| 25151 | MYSQL_SYSVAR(log_write_max_size), | ||
| 25152 | MYSQL_SYSVAR(log_writer_spin_delay), | ||
| 25153 | MYSQL_SYSVAR(log_writer_timeout), | ||
| 25154 | MYSQL_SYSVAR(log_checkpoint_every), | ||
| 25155 | MYSQL_SYSVAR(log_flusher_spin_delay), | ||
| 25156 | MYSQL_SYSVAR(log_flusher_timeout), | ||
| 25157 | MYSQL_SYSVAR(log_write_notifier_spin_delay), | ||
| 25158 | MYSQL_SYSVAR(log_write_notifier_timeout), | ||
| 25159 | MYSQL_SYSVAR(log_flush_notifier_spin_delay), | ||
| 25160 | MYSQL_SYSVAR(log_flush_notifier_timeout), | ||
| 25161 | #endif /* ENABLE_EXPERIMENT_SYSVARS */ | ||
| 25162 | MYSQL_SYSVAR(log_compressed_pages), | ||
| 25163 | MYSQL_SYSVAR(max_dirty_pages_pct), | ||
| 25164 | MYSQL_SYSVAR(max_dirty_pages_pct_lwm), | ||
| 25165 | MYSQL_SYSVAR(adaptive_flushing_lwm), | ||
| 25166 | MYSQL_SYSVAR(adaptive_flushing), | ||
| 25167 | MYSQL_SYSVAR(flush_sync), | ||
| 25168 | MYSQL_SYSVAR(flushing_avg_loops), | ||
| 25169 | MYSQL_SYSVAR(max_purge_lag), | ||
| 25170 | MYSQL_SYSVAR(max_purge_lag_delay), | ||
| 25171 | MYSQL_SYSVAR(old_blocks_pct), | ||
| 25172 | MYSQL_SYSVAR(old_blocks_time), | ||
| 25173 | MYSQL_SYSVAR(open_files), | ||
| 25174 | MYSQL_SYSVAR(optimize_fulltext_only), | ||
| 25175 | MYSQL_SYSVAR(rollback_on_timeout), | ||
| 25176 | MYSQL_SYSVAR(ft_aux_table), | ||
| 25177 | MYSQL_SYSVAR(ft_enable_diag_print), | ||
| 25178 | MYSQL_SYSVAR(ft_server_stopword_table), | ||
| 25179 | MYSQL_SYSVAR(ft_user_stopword_table), | ||
| 25180 | MYSQL_SYSVAR(disable_sort_file_cache), | ||
| 25181 | MYSQL_SYSVAR(stats_on_metadata), | ||
| 25182 | MYSQL_SYSVAR(stats_transient_sample_pages), | ||
| 25183 | MYSQL_SYSVAR(stats_persistent), | ||
| 25184 | MYSQL_SYSVAR(stats_persistent_sample_pages), | ||
| 25185 | MYSQL_SYSVAR(stats_auto_recalc), | ||
| 25186 | MYSQL_SYSVAR(adaptive_hash_index), | ||
| 25187 | MYSQL_SYSVAR(adaptive_hash_index_parts), | ||
| 25188 | MYSQL_SYSVAR(stats_method), | ||
| 25189 | MYSQL_SYSVAR(replication_delay), | ||
| 25190 | MYSQL_SYSVAR(status_file), | ||
| 25191 | MYSQL_SYSVAR(strict_mode), | ||
| 25192 | MYSQL_SYSVAR(sort_buffer_size), | ||
| 25193 | MYSQL_SYSVAR(online_alter_log_max_size), | ||
| 25194 | MYSQL_SYSVAR(directories), | ||
| 25195 | MYSQL_SYSVAR(sync_spin_loops), | ||
| 25196 | MYSQL_SYSVAR(spin_wait_delay), | ||
| 25197 | MYSQL_SYSVAR(spin_wait_pause_multiplier), | ||
| 25198 | MYSQL_SYSVAR(fsync_threshold), | ||
| 25199 | MYSQL_SYSVAR(table_locks), | ||
| 25200 | MYSQL_SYSVAR(thread_concurrency), | ||
| 25201 | MYSQL_SYSVAR(adaptive_max_sleep_delay), | ||
| 25202 | MYSQL_SYSVAR(thread_sleep_delay), | ||
| 25203 | MYSQL_SYSVAR(tmpdir), | ||
| 25204 | MYSQL_SYSVAR(autoinc_lock_mode), | ||
| 25205 | MYSQL_SYSVAR(show_locks_held), | ||
| 25206 | MYSQL_SYSVAR(version), | ||
| 25207 | MYSQL_SYSVAR(use_native_aio), | ||
| 25208 | #ifdef HAVE_LIBNUMA | ||
| 25209 | MYSQL_SYSVAR(numa_interleave), | ||
| 25210 | #endif /* HAVE_LIBNUMA */ | ||
| 25211 | MYSQL_SYSVAR(change_buffering), | ||
| 25212 | MYSQL_SYSVAR(change_buffer_max_size), | ||
| 25213 | #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG | ||
| 25214 | MYSQL_SYSVAR(change_buffering_debug), | ||
| 25215 | MYSQL_SYSVAR(disable_background_merge), | ||
| 25216 | #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ | ||
| 25217 | MYSQL_SYSVAR(random_read_ahead), | ||
| 25218 | MYSQL_SYSVAR(read_ahead_threshold), | ||
| 25219 | MYSQL_SYSVAR(read_only), | ||
| 25220 | |||
| 25221 | MYSQL_SYSVAR(io_capacity), | ||
| 25222 | MYSQL_SYSVAR(io_capacity_max), | ||
| 25223 | MYSQL_SYSVAR(idle_flush_pct), | ||
| 25224 | MYSQL_SYSVAR(page_cleaners), | ||
| 25225 | MYSQL_SYSVAR(monitor_enable), | ||
| 25226 | MYSQL_SYSVAR(monitor_disable), | ||
| 25227 | MYSQL_SYSVAR(monitor_reset), | ||
| 25228 | MYSQL_SYSVAR(monitor_reset_all), | ||
| 25229 | MYSQL_SYSVAR(purge_threads), | ||
| 25230 | MYSQL_SYSVAR(purge_batch_size), | ||
| 25231 | #ifdef UNIV_DEBUG | ||
| 25232 | MYSQL_SYSVAR(background_drop_list_empty), | ||
| 25233 | MYSQL_SYSVAR(purge_run_now), | ||
| 25234 | MYSQL_SYSVAR(purge_stop_now), | ||
| 25235 | MYSQL_SYSVAR(log_flush_now), | ||
| 25236 | MYSQL_SYSVAR(log_checkpoint_now), | ||
| 25237 | MYSQL_SYSVAR(log_checkpoint_fuzzy_now), | ||
| 25238 | MYSQL_SYSVAR(checkpoint_disabled), | ||
| 25239 | MYSQL_SYSVAR(buf_flush_list_now), | ||
| 25240 | MYSQL_SYSVAR(merge_threshold_set_all_debug), | ||
| 25241 | MYSQL_SYSVAR(semaphore_wait_timeout_debug), | ||
| 25242 | #endif /* UNIV_DEBUG */ | ||
| 25243 | #if defined UNIV_DEBUG || defined UNIV_PERF_DEBUG | ||
| 25244 | MYSQL_SYSVAR(page_hash_locks), | ||
| 25245 | #ifdef UNIV_LINUX | ||
| 25246 | MYSQL_SYSVAR(sched_priority_purge), | ||
| 25247 | MYSQL_SYSVAR(sched_priority_io), | ||
| 25248 | MYSQL_SYSVAR(sched_priority_master), | ||
| 25249 | MYSQL_SYSVAR(priority_purge), | ||
| 25250 | MYSQL_SYSVAR(priority_master), | ||
| 25251 | #endif /* UNIV_LINUX */ | ||
| 25252 | MYSQL_SYSVAR(cleaner_max_lru_time), | ||
| 25253 | MYSQL_SYSVAR(cleaner_max_flush_time), | ||
| 25254 | #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ | ||
| 25255 | MYSQL_SYSVAR(validate_tablespace_paths), | ||
| 25256 | MYSQL_SYSVAR(use_fdatasync), | ||
| 25257 | MYSQL_SYSVAR(status_output), | ||
| 25258 | MYSQL_SYSVAR(status_output_locks), | ||
| 25259 | MYSQL_SYSVAR(cleaner_lsn_age_factor), | ||
| 25260 | MYSQL_SYSVAR(empty_free_list_algorithm), | ||
| 25261 | MYSQL_SYSVAR(print_all_deadlocks), | ||
| 25262 | MYSQL_SYSVAR(print_lock_wait_timeout_info), | ||
| 25263 | MYSQL_SYSVAR(cmp_per_index_enabled), | ||
| 25264 | MYSQL_SYSVAR(max_undo_log_size), | ||
| 25265 | MYSQL_SYSVAR(purge_rseg_truncate_frequency), | ||
| 25266 | MYSQL_SYSVAR(undo_log_truncate), | ||
| 25267 | MYSQL_SYSVAR(undo_log_encrypt), | ||
| 25268 | MYSQL_SYSVAR(rollback_segments), | ||
| 25269 | MYSQL_SYSVAR(undo_directory), | ||
| 25270 | MYSQL_SYSVAR(temp_tablespaces_dir), | ||
| 25271 | MYSQL_SYSVAR(undo_tablespaces), | ||
| 25272 | MYSQL_SYSVAR(sync_array_size), | ||
| 25273 | MYSQL_SYSVAR(compression_failure_threshold_pct), | ||
| 25274 | MYSQL_SYSVAR(compression_pad_pct_max), | ||
| 25275 | MYSQL_SYSVAR(default_row_format), | ||
| 25276 | MYSQL_SYSVAR(redo_log_archive_dirs), | ||
| 25277 | MYSQL_SYSVAR(redo_log_encrypt), | ||
| 25278 | MYSQL_SYSVAR(print_ddl_logs), | ||
| 25279 | #ifdef UNIV_DEBUG | ||
| 25280 | MYSQL_SYSVAR(trx_rseg_n_slots_debug), | ||
| 25281 | MYSQL_SYSVAR(limit_optimistic_insert_debug), | ||
| 25282 | MYSQL_SYSVAR(trx_purge_view_update_only_debug), | ||
| 25283 | MYSQL_SYSVAR(fil_make_page_dirty_debug), | ||
| 25284 | MYSQL_SYSVAR(saved_page_number_debug), | ||
| 25285 | MYSQL_SYSVAR(compress_debug), | ||
| 25286 | MYSQL_SYSVAR(page_cleaner_disabled_debug), | ||
| 25287 | MYSQL_SYSVAR(dict_stats_disabled_debug), | ||
| 25288 | MYSQL_SYSVAR(master_thread_disabled_debug), | ||
| 25289 | MYSQL_SYSVAR(sync_debug), | ||
| 25290 | MYSQL_SYSVAR(buffer_pool_debug), | ||
| 25291 | MYSQL_SYSVAR(ddl_log_crash_reset_debug), | ||
| 25292 | MYSQL_SYSVAR(interpreter), | ||
| 25293 | MYSQL_SYSVAR(interpreter_output), | ||
| 25294 | #endif /* UNIV_DEBUG */ | ||
| 25295 | MYSQL_SYSVAR(parallel_read_threads), | ||
| 25296 | MYSQL_SYSVAR(segment_reserve_factor), | ||
| 25297 | MYSQL_SYSVAR(corrupt_table_action), | ||
| 25298 | MYSQL_SYSVAR(parallel_doublewrite_path), | ||
| 25299 | MYSQL_SYSVAR(parallel_dblwr_encrypt), | ||
| 25300 | MYSQL_SYSVAR(compressed_columns_zip_level), | ||
| 25301 | MYSQL_SYSVAR(compressed_columns_threshold), | ||
| 25302 | MYSQL_SYSVAR(ft_ignore_stopwords), | ||
| 25303 | MYSQL_SYSVAR(encrypt_online_alter_logs), | ||
| 25304 | MYSQL_SYSVAR(encryption_threads), | ||
| 25305 | MYSQL_SYSVAR(encryption_rotate_key_age), | ||
| 25306 | MYSQL_SYSVAR(encryption_rotation_iops), | ||
| 25307 | MYSQL_SYSVAR(default_encryption_key_id), | ||
| 25308 | MYSQL_SYSVAR(records_in_range), | ||
| 25309 | MYSQL_SYSVAR(force_index_records_in_range), | ||
| 25310 | nullptr}; | ||
| 25311 | |||
| 25312 | mysql_declare_plugin(innobase){ | ||
| 25313 | MYSQL_STORAGE_ENGINE_PLUGIN, | ||
| 25314 | &innobase_storage_engine, | ||
| 25315 | innobase_hton_name, | ||
| 25316 | PLUGIN_AUTHOR_ORACLE, | ||
| 25317 | "Percona-XtraDB, Supports transactions, row-level locking, and foreign " | ||
| 25318 | "keys", | ||
| 25319 | PLUGIN_LICENSE_GPL, | ||
| 25320 | innodb_init, /* Plugin Init */ | ||
| 25321 | nullptr, /* Plugin Check uninstall */ | ||
| 25322 | innodb_deinit, /* Plugin Deinit */ | ||
| 25323 | INNODB_VERSION_SHORT, | ||
| 25324 | innodb_status_variables_export, /* status variables */ | ||
| 25325 | innobase_system_variables, /* system variables */ | ||
| 25326 | nullptr, /* reserved */ | ||
| 25327 | 0, /* flags */ | ||
| 25328 | }, | ||
| 25329 | i_s_innodb_trx, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem, | ||
| 25330 | i_s_innodb_cmpmem_reset, i_s_innodb_cmp_per_index, | ||
| 25331 | i_s_innodb_cmp_per_index_reset, i_s_innodb_buffer_page, | ||
| 25332 | i_s_innodb_buffer_page_lru, i_s_innodb_buffer_stats, | ||
| 25333 | i_s_innodb_temp_table_info, i_s_innodb_metrics, | ||
| 25334 | i_s_innodb_ft_default_stopword, i_s_innodb_ft_deleted, | ||
| 25335 | i_s_innodb_ft_being_deleted, i_s_innodb_ft_config, | ||
| 25336 | i_s_innodb_ft_index_cache, i_s_innodb_ft_index_table, i_s_innodb_tables, | ||
| 25337 | i_s_innodb_tablestats, i_s_innodb_indexes, i_s_innodb_tablespaces, | ||
| 25338 | i_s_innodb_columns, i_s_innodb_virtual, i_s_innodb_cached_indexes, | ||
| 25339 | i_s_innodb_session_temp_tablespaces, | ||
| 25340 | i_s_innodb_tablespaces_encryption | ||
| 25341 | |||
| 25342 | mysql_declare_plugin_end; | ||
| 25343 | |||
| 25344 | /** @brief Initialize the default value of innodb_commit_concurrency. | ||
| 25345 | |||
| 25346 | Once InnoDB is running, the innodb_commit_concurrency must not change | ||
| 25347 | from zero to nonzero. (Bug #42101) | ||
| 25348 | |||
| 25349 | The initial default value is 0, and without this extra initialization, | ||
| 25350 | SET GLOBAL innodb_commit_concurrency=DEFAULT would set the parameter | ||
| 25351 | to 0, even if it was initially set to nonzero at the command line | ||
| 25352 | or configuration file. */ | ||
| 25353 | 12027 | static void innobase_commit_concurrency_init_default() { | |
| 25354 | 12027 | MYSQL_SYSVAR_NAME(commit_concurrency).def_val = innobase_commit_concurrency; | |
| 25355 | 12027 | } | |
| 25356 | |||
| 25357 | /**************************************************************************** | ||
| 25358 | DS-MRR implementation | ||
| 25359 | ***************************************************************************/ | ||
| 25360 | |||
| 25361 | /** | ||
| 25362 | Multi Range Read interface, DS-MRR calls */ | ||
| 25363 | 621300 | int ha_innobase::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param, | |
| 25364 | uint n_ranges, uint mode, | ||
| 25365 | HANDLER_BUFFER *buf) { | ||
| 25366 | 621300 | m_ds_mrr.init(table); | |
| 25367 | |||
| 25368 | 621325 | return (m_ds_mrr.dsmrr_init(seq, seq_init_param, n_ranges, mode, buf)); | |
| 25369 | } | ||
| 25370 | |||
| 25371 | 3536410 | int ha_innobase::multi_range_read_next(char **range_info) { | |
| 25372 | 3536410 | return (m_ds_mrr.dsmrr_next(range_info)); | |
| 25373 | } | ||
| 25374 | |||
| 25375 | 603027 | ha_rows ha_innobase::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, | |
| 25376 | void *seq_init_param, | ||
| 25377 | uint n_ranges, uint *bufsz, | ||
| 25378 | uint *flags, | ||
| 25379 | Cost_estimate *cost) { | ||
| 25380 | /* See comments in ha_myisam::multi_range_read_info_const */ | ||
| 25381 | 603027 | m_ds_mrr.init(table); | |
| 25382 | |||
| 25383 | 603053 | return (m_ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz, | |
| 25384 | 603109 | flags, cost)); | |
| 25385 | } | ||
| 25386 | |||
| 25387 | 1302 | ha_rows ha_innobase::multi_range_read_info(uint keyno, uint n_ranges, uint keys, | |
| 25388 | uint *bufsz, uint *flags, | ||
| 25389 | Cost_estimate *cost) { | ||
| 25390 | 1302 | m_ds_mrr.init(table); | |
| 25391 | |||
| 25392 | 1302 | return (m_ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost)); | |
| 25393 | } | ||
| 25394 | |||
| 25395 | /** | ||
| 25396 | Index Condition Pushdown interface implementation */ | ||
| 25397 | |||
| 25398 | /** InnoDB index push-down condition check | ||
| 25399 | @return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */ | ||
| 25400 | ICP_RESULT | ||
| 25401 | 1114114 | innobase_index_cond(ha_innobase *h) /*!< in/out: pointer to ha_innobase */ | |
| 25402 | { | ||
| 25403 |
1/2✓ Branch 0 taken 1114114 times.
✗ Branch 1 not taken.
|
1114114 | DBUG_TRACE; |
| 25404 | |||
| 25405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1114114 times.
|
1114114 | assert(h->pushed_idx_cond); |
| 25406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1114114 times.
|
1114114 | assert(h->pushed_idx_cond_keyno != MAX_KEY); |
| 25407 | |||
| 25408 |
7/8✓ Branch 0 taken 6853 times.
✓ Branch 1 taken 1107261 times.
✓ Branch 2 taken 6853 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 657 times.
✓ Branch 5 taken 6196 times.
✓ Branch 6 taken 657 times.
✓ Branch 7 taken 1113457 times.
|
1114114 | if (h->end_range && h->compare_key_icp(h->end_range) > 0) { |
| 25409 | /* caller should return HA_ERR_END_OF_FILE already */ | ||
| 25410 | 657 | return ICP_OUT_OF_RANGE; | |
| 25411 | } | ||
| 25412 | |||
| 25413 |
3/4✓ Branch 0 taken 1113457 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1111700 times.
✓ Branch 3 taken 1757 times.
|
1113457 | return h->pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH; |
| 25414 | 1114114 | } | |
| 25415 | |||
| 25416 | /** Get the computed value by supplying the base column values. | ||
| 25417 | @param[in,out] table the table whose virtual column template to be built */ | ||
| 25418 | 1 | void innobase_init_vc_templ(dict_table_t *table) { | |
| 25419 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dict_sys_mutex_enter(); |
| 25420 | |||
| 25421 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (table->vc_templ != nullptr) { |
| 25422 | ✗ | dict_sys_mutex_exit(); | |
| 25423 | |||
| 25424 | ✗ | return; | |
| 25425 | } | ||
| 25426 | |||
| 25427 | 1 | table->vc_templ = | |
| 25428 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ut::new_withkey<dict_vcol_templ_t>(UT_NEW_THIS_FILE_PSI_KEY); |
| 25429 | 1 | table->vc_templ->vtempl = nullptr; | |
| 25430 | |||
| 25431 | 1 | std::string schema_name; | |
| 25432 | 1 | std::string table_name; | |
| 25433 | |||
| 25434 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | table->get_table_name(schema_name, table_name); |
| 25435 | |||
| 25436 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | THD *thd = current_thd; |
| 25437 | |||
| 25438 | { | ||
| 25439 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | innodb_session_dict_mutex_guard_t guard(*thd_to_innodb_session(thd)); |
| 25440 | #ifdef UNIV_DEBUG | ||
| 25441 | bool ret = | ||
| 25442 | #endif /* UNIV_DEBUG */ | ||
| 25443 | |||
| 25444 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | handler::my_prepare_gcolumn_template( |
| 25445 | thd, schema_name.c_str(), table_name.c_str(), | ||
| 25446 | &innobase_build_v_templ_callback, static_cast<void *>(table)); | ||
| 25447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | ut_ad(!ret); |
| 25448 | 1 | } | |
| 25449 | |||
| 25450 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | dict_sys_mutex_exit(); |
| 25451 | 1 | } | |
| 25452 | |||
| 25453 | /** Change dbname and table name in table->vc_templ. | ||
| 25454 | @param[in,out] table the table whose virtual column template | ||
| 25455 | dbname and tbname to be renamed. */ | ||
| 25456 | 568 | void innobase_rename_vc_templ(dict_table_t *table) { | |
| 25457 | 568 | std::string schema_name; | |
| 25458 | 568 | std::string table_name; | |
| 25459 | |||
| 25460 | /* Get table and schema name in system character set. */ | ||
| 25461 |
1/2✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
|
568 | table->get_table_name(schema_name, table_name); |
| 25462 | |||
| 25463 |
1/2✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
|
568 | table->vc_templ->db_name.assign(schema_name); |
| 25464 |
1/2✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
|
568 | table->vc_templ->tb_name.assign(table_name); |
| 25465 | 568 | } | |
| 25466 | |||
| 25467 | 35 | dfield_t *innobase_get_field_from_update_vector(dict_foreign_t *foreign, | |
| 25468 | upd_t *update, | ||
| 25469 | uint32_t col_no) { | ||
| 25470 | 35 | dict_table_t *parent_table = foreign->referenced_table; | |
| 25471 | 35 | dict_index_t *parent_index = foreign->referenced_index; | |
| 25472 | uint32_t parent_field_no; | ||
| 25473 | uint32_t parent_col_no; | ||
| 25474 | uint32_t child_col_no; | ||
| 25475 | |||
| 25476 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 11 times.
|
46 | for (uint32_t i = 0; i < foreign->n_fields; i++) { |
| 25477 | 35 | child_col_no = foreign->foreign_index->get_col_no(i); | |
| 25478 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 24 times.
|
35 | if (child_col_no != col_no) { |
| 25479 | 11 | continue; | |
| 25480 | } | ||
| 25481 | 24 | parent_col_no = parent_index->get_col_no(i); | |
| 25482 | 24 | parent_field_no = dict_table_get_nth_col_pos(parent_table, parent_col_no); | |
| 25483 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | for (uint32_t j = 0; j < update->n_fields; j++) { |
| 25484 | 24 | upd_field_t *parent_ufield = &update->fields[j]; | |
| 25485 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | if (parent_ufield->field_no == parent_field_no) { |
| 25486 | 24 | return (&parent_ufield->new_val); | |
| 25487 | } | ||
| 25488 | } | ||
| 25489 | } | ||
| 25490 | |||
| 25491 | 11 | return (nullptr); | |
| 25492 | } | ||
| 25493 | |||
| 25494 | /** Get the computed value by supplying the base column values. | ||
| 25495 | @param[in,out] row the data row | ||
| 25496 | @param[in] col virtual column | ||
| 25497 | @param[in] index index on the virtual column | ||
| 25498 | @param[in,out] local_heap heap memory for processing large data etc. | ||
| 25499 | @param[in,out] heap memory heap that copies the actual index row | ||
| 25500 | @param[in] ifield index field | ||
| 25501 | @param[in] thd MySQL thread handle | ||
| 25502 | @param[in,out] mysql_table mysql table object | ||
| 25503 | @param[in] old_table during ALTER TABLE, this is the old table | ||
| 25504 | or NULL. | ||
| 25505 | @param[in] parent_update update vector for the parent row | ||
| 25506 | @param[in] foreign foreign key information | ||
| 25507 | @param[in] compress_heap | ||
| 25508 | @return the field filled with computed value, or NULL if just want | ||
| 25509 | to store the value in passed in "my_rec" */ | ||
| 25510 | 34420 | dfield_t *innobase_get_computed_value( | |
| 25511 | const dtuple_t *row, const dict_v_col_t *col, const dict_index_t *index, | ||
| 25512 | mem_heap_t **local_heap, mem_heap_t *heap, const dict_field_t *ifield, | ||
| 25513 | THD *thd, TABLE *mysql_table, const dict_table_t *old_table, | ||
| 25514 | upd_t *parent_update, dict_foreign_t *foreign, mem_heap_t **compress_heap) { | ||
| 25515 | byte rec_buf1[REC_VERSION_56_MAX_INDEX_COL_LEN]; | ||
| 25516 | byte rec_buf2[REC_VERSION_56_MAX_INDEX_COL_LEN]; | ||
| 25517 | byte *mysql_rec; | ||
| 25518 | byte *buf; | ||
| 25519 | dfield_t *field; | ||
| 25520 | ulint len; | ||
| 25521 | 34420 | ulong mv_length = 0; | |
| 25522 | 34420 | const char *mv_data_ptr = nullptr; | |
| 25523 | |||
| 25524 | const page_size_t page_size = (old_table == nullptr) | ||
| 25525 |
1/2✓ Branch 0 taken 7812 times.
✗ Branch 1 not taken.
|
7812 | ? dict_table_page_size(index->table) |
| 25526 |
3/4✓ Branch 0 taken 7812 times.
✓ Branch 1 taken 26608 times.
✓ Branch 2 taken 26608 times.
✗ Branch 3 not taken.
|
34420 | : dict_table_page_size(old_table); |
| 25527 | |||
| 25528 | 34420 | const dict_index_t *clust_index = nullptr; | |
| 25529 |
2/2✓ Branch 0 taken 7812 times.
✓ Branch 1 taken 26608 times.
|
34420 | if (old_table == nullptr) { |
| 25530 |
1/2✓ Branch 0 taken 7812 times.
✗ Branch 1 not taken.
|
7812 | clust_index = index->table->first_index(); |
| 25531 | } else { | ||
| 25532 |
1/2✓ Branch 0 taken 26608 times.
✗ Branch 1 not taken.
|
26608 | clust_index = old_table->first_index(); |
| 25533 | } | ||
| 25534 | |||
| 25535 | 34420 | ulint ret = 0; | |
| 25536 | |||
| 25537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34420 times.
|
34420 | ut_ad(index->table->vc_templ); |
| 25538 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34420 times.
|
34420 | ut_ad(thd != nullptr); |
| 25539 | |||
| 25540 | 34420 | const mysql_row_templ_t *vctempl = | |
| 25541 | 34420 | index->table->vc_templ | |
| 25542 | 34420 | ->vtempl[index->table->vc_templ->n_col + col->v_pos]; | |
| 25543 | |||
| 25544 |
2/2✓ Branch 0 taken 32961 times.
✓ Branch 1 taken 1459 times.
|
34420 | if (!heap || |
| 25545 |
2/2✓ Branch 0 taken 6421 times.
✓ Branch 1 taken 26540 times.
|
32961 | index->table->vc_templ->rec_len >= REC_VERSION_56_MAX_INDEX_COL_LEN) { |
| 25546 |
2/2✓ Branch 0 taken 3379 times.
✓ Branch 1 taken 4501 times.
|
7880 | if (*local_heap == nullptr) { |
| 25547 |
1/2✓ Branch 0 taken 3379 times.
✗ Branch 1 not taken.
|
3379 | *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE); |
| 25548 | } | ||
| 25549 | |||
| 25550 | mysql_rec = static_cast<byte *>( | ||
| 25551 |
1/2✓ Branch 0 taken 7880 times.
✗ Branch 1 not taken.
|
7880 | mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len)); |
| 25552 | 7880 | buf = static_cast<byte *>( | |
| 25553 |
1/2✓ Branch 0 taken 7880 times.
✗ Branch 1 not taken.
|
7880 | mem_heap_alloc(*local_heap, index->table->vc_templ->rec_len)); |
| 25554 | } else { | ||
| 25555 | 26540 | mysql_rec = rec_buf1; | |
| 25556 | 26540 | buf = rec_buf2; | |
| 25557 | } | ||
| 25558 | |||
| 25559 |
2/2✓ Branch 0 taken 38287 times.
✓ Branch 1 taken 34420 times.
|
72707 | for (ulint i = 0; i < col->num_base; i++) { |
| 25560 | 38287 | dict_col_t *base_col = col->base_col[i]; | |
| 25561 | 38287 | const dfield_t *row_field = nullptr; | |
| 25562 | 38287 | uint32_t col_no = base_col->ind; | |
| 25563 | 38287 | const mysql_row_templ_t *templ = index->table->vc_templ->vtempl[col_no]; | |
| 25564 | const byte *data; | ||
| 25565 | |||
| 25566 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 38256 times.
|
38287 | if (parent_update != nullptr) { |
| 25567 | row_field = | ||
| 25568 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
31 | innobase_get_field_from_update_vector(foreign, parent_update, col_no); |
| 25569 | } | ||
| 25570 | |||
| 25571 |
2/2✓ Branch 0 taken 38265 times.
✓ Branch 1 taken 22 times.
|
38287 | if (row_field == nullptr) { |
| 25572 |
1/2✓ Branch 0 taken 38265 times.
✗ Branch 1 not taken.
|
38265 | row_field = dtuple_get_nth_field(row, col_no); |
| 25573 | } | ||
| 25574 | |||
| 25575 | 38287 | data = static_cast<const byte *>(row_field->data); | |
| 25576 | 38287 | len = row_field->len; | |
| 25577 | |||
| 25578 |
2/2✓ Branch 0 taken 135 times.
✓ Branch 1 taken 38152 times.
|
38287 | if (row_field->ext) { |
| 25579 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 128 times.
|
135 | if (*local_heap == nullptr) { |
| 25580 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | *local_heap = mem_heap_create(UNIV_PAGE_SIZE, UT_LOCATION_HERE); |
| 25581 | } | ||
| 25582 | |||
| 25583 | 135 | data = lob::btr_copy_externally_stored_field( | |
| 25584 |
1/2✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
|
135 | thd_to_trx(thd), clust_index, &len, nullptr, data, page_size, |
| 25585 |
2/4✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 135 times.
✗ Branch 3 not taken.
|
135 | dfield_get_len(row_field), false, *local_heap); |
| 25586 | } | ||
| 25587 | |||
| 25588 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 38218 times.
|
38287 | if (len == UNIV_SQL_NULL) { |
| 25589 | 69 | mysql_rec[templ->mysql_null_byte_offset] |= | |
| 25590 | 69 | (byte)templ->mysql_null_bit_mask; | |
| 25591 | 69 | memcpy(mysql_rec + templ->mysql_col_offset, | |
| 25592 | 69 | static_cast<const byte *>(index->table->vc_templ->default_rec + | |
| 25593 | 69 | templ->mysql_col_offset), | |
| 25594 | 69 | templ->mysql_col_len); | |
| 25595 | } else { | ||
| 25596 | 38218 | row_sel_field_store_in_mysql_format( | |
| 25597 | 38218 | mysql_rec + templ->mysql_col_offset, templ, index, | |
| 25598 |
1/2✓ Branch 0 taken 38218 times.
✗ Branch 1 not taken.
|
38218 | templ->clust_rec_field_no, (const byte *)data, len, compress_heap, |
| 25599 | ULINT_UNDEFINED); | ||
| 25600 | |||
| 25601 |
2/2✓ Branch 0 taken 21992 times.
✓ Branch 1 taken 16226 times.
|
38218 | if (templ->mysql_null_bit_mask) { |
| 25602 | /* It is a nullable column with a | ||
| 25603 | non-NULL value */ | ||
| 25604 | 21992 | mysql_rec[templ->mysql_null_byte_offset] &= | |
| 25605 | 21992 | ~(byte)templ->mysql_null_bit_mask; | |
| 25606 | } | ||
| 25607 | } | ||
| 25608 | } | ||
| 25609 | |||
| 25610 |
1/2✓ Branch 0 taken 34420 times.
✗ Branch 1 not taken.
|
34420 | field = dtuple_get_nth_v_field(row, col->v_pos); |
| 25611 | |||
| 25612 | /* Bitmap for specifying which virtual columns the server | ||
| 25613 | should evaluate */ | ||
| 25614 | 34420 | MY_BITMAP column_map; | |
| 25615 | my_bitmap_map col_map_storage[bitmap_buffer_size(REC_MAX_N_FIELDS)]; | ||
| 25616 | |||
| 25617 |
1/2✓ Branch 0 taken 34420 times.
✗ Branch 1 not taken.
|
34420 | bitmap_init(&column_map, col_map_storage, REC_MAX_N_FIELDS); |
| 25618 | |||
| 25619 | /* Specify the column the server should evaluate */ | ||
| 25620 | 34420 | bitmap_set_bit(&column_map, col->m_col.ind); | |
| 25621 | |||
| 25622 | 34420 | Temp_table_handle tblhdl; | |
| 25623 | |||
| 25624 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 34344 times.
|
34420 | if (mysql_table == nullptr) { |
| 25625 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
|
76 | if (vctempl->type == DATA_BLOB) { |
| 25626 | ulint max_len; | ||
| 25627 | |||
| 25628 | ✗ | if (vctempl->mysql_col_len - 8 == 1) { | |
| 25629 | /* This is for TINYBLOB only, which needs | ||
| 25630 | only 1 byte, other BLOBs won't be affected */ | ||
| 25631 | ✗ | max_len = 255; | |
| 25632 | } else { | ||
| 25633 | ✗ | max_len = DICT_MAX_FIELD_LEN_BY_FORMAT(index->table) + 1; | |
| 25634 | } | ||
| 25635 | |||
| 25636 | ✗ | byte *blob_mem = static_cast<byte *>(mem_heap_alloc(heap, max_len)); | |
| 25637 | |||
| 25638 | ✗ | row_mysql_store_blob_ref(mysql_rec + vctempl->mysql_col_offset, | |
| 25639 | ✗ | vctempl->mysql_col_len, blob_mem, max_len, false, | |
| 25640 | 0, 0, compress_heap); | ||
| 25641 | } | ||
| 25642 | |||
| 25643 | /* open a temporary table handle */ | ||
| 25644 |
1/2✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
|
76 | mysql_table = tblhdl.open(thd, index->table->vc_templ->db_name.c_str(), |
| 25645 | 76 | index->table->vc_templ->tb_name.c_str()); | |
| 25646 | } | ||
| 25647 |
1/2✓ Branch 0 taken 34420 times.
✗ Branch 1 not taken.
|
34420 | if (mysql_table) { |
| 25648 |
5/6✓ Branch 0 taken 25421 times.
✓ Branch 1 taken 8999 times.
✓ Branch 2 taken 25421 times.
✓ Branch 3 taken 8999 times.
✓ Branch 4 taken 34420 times.
✗ Branch 5 not taken.
|
68840 | ret = handler::my_eval_gcolumn_expr( |
| 25649 | thd, mysql_table, &column_map, (uchar *)mysql_rec, | ||
| 25650 | 34420 | (col->m_col.is_multi_value() ? &mv_data_ptr : nullptr), | |
| 25651 | 34420 | (col->m_col.is_multi_value() ? &mv_length : nullptr)); | |
| 25652 | } else { | ||
| 25653 | ✗ | return nullptr; | |
| 25654 | } | ||
| 25655 | |||
| 25656 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 34389 times.
|
34420 | if (ret != 0) { |
| 25657 | #ifdef INNODB_VIRTUAL_DEBUG | ||
| 25658 | ib::warn(ER_IB_MSG_581) << "Compute virtual column values failed "; | ||
| 25659 | fputs("InnoDB: Cannot compute value for following record ", stderr); | ||
| 25660 | dtuple_print(stderr, row); | ||
| 25661 | #endif /* INNODB_VIRTUAL_DEBUG */ | ||
| 25662 | 31 | return (nullptr); | |
| 25663 | } | ||
| 25664 | |||
| 25665 |
2/2✓ Branch 0 taken 34287 times.
✓ Branch 1 taken 102 times.
|
34389 | if (vctempl->mysql_null_bit_mask && |
| 25666 | 34287 | (mysql_rec[vctempl->mysql_null_byte_offset] & | |
| 25667 |
2/2✓ Branch 0 taken 124 times.
✓ Branch 1 taken 34163 times.
|
34287 | vctempl->mysql_null_bit_mask)) { |
| 25668 |
1/2✓ Branch 0 taken 124 times.
✗ Branch 1 not taken.
|
124 | dfield_set_null(field); |
| 25669 | 124 | field->type.prtype |= DATA_VIRTUAL; | |
| 25670 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 58 times.
|
124 | if (col->m_col.is_multi_value()) { |
| 25671 | 66 | field->type.prtype |= DATA_MULTI_VALUE; | |
| 25672 | } | ||
| 25673 | 124 | return (field); | |
| 25674 | } | ||
| 25675 | |||
| 25676 |
2/2✓ Branch 0 taken 25327 times.
✓ Branch 1 taken 8938 times.
|
34265 | if (col->m_col.is_multi_value()) { |
| 25677 | Field_typed_array *fld; | ||
| 25678 | 25327 | fld = down_cast<Field_typed_array *>(mysql_table->field[col->m_col.ind]); | |
| 25679 |
1/2✓ Branch 0 taken 25327 times.
✗ Branch 1 not taken.
|
25327 | json_binary::Value v(json_binary::parse_binary(mv_data_ptr, mv_length)); |
| 25680 | 25327 | multi_value_data *value = nullptr; | |
| 25681 | |||
| 25682 | 50654 | bool succ = innobase_store_multi_value( | |
| 25683 |
2/4✓ Branch 0 taken 25327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25327 times.
✗ Branch 3 not taken.
|
25327 | v, value, fld, field, dict_table_is_comp(index->table), heap); |
| 25684 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25327 times.
|
25327 | if (!succ) { |
| 25685 | ✗ | ut_error; | |
| 25686 | } | ||
| 25687 | |||
| 25688 | 25327 | field->type.prtype |= DATA_MULTI_VALUE; | |
| 25689 | } else { | ||
| 25690 | 8938 | row_mysql_store_col_in_innobase_format( | |
| 25691 | 8938 | field, buf, true, mysql_rec + vctempl->mysql_col_offset, | |
| 25692 |
2/4✓ Branch 0 taken 8938 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8938 times.
✗ Branch 3 not taken.
|
8938 | vctempl->mysql_col_len, dict_table_is_comp(index->table), false, |
| 25693 | nullptr, 0, nullptr); | ||
| 25694 | } | ||
| 25695 | 34265 | field->type.prtype |= DATA_VIRTUAL; | |
| 25696 | |||
| 25697 | 34265 | ulint max_prefix = col->m_col.max_prefix; | |
| 25698 | |||
| 25699 |
4/4✓ Branch 0 taken 7372 times.
✓ Branch 1 taken 26893 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 7242 times.
|
34265 | if (max_prefix && ifield && |
| 25700 |
2/4✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 130 times.
|
130 | (ifield->prefix_len == 0 || ifield->prefix_len > col->m_col.max_prefix)) { |
| 25701 | ✗ | max_prefix = ifield->prefix_len; | |
| 25702 | } | ||
| 25703 | |||
| 25704 | /* If this is a prefix index, we only need a portion of the field */ | ||
| 25705 |
2/2✓ Branch 0 taken 7372 times.
✓ Branch 1 taken 26893 times.
|
34265 | if (max_prefix) { |
| 25706 | 14744 | len = dtype_get_at_most_n_mbchars( | |
| 25707 | 7372 | col->m_col.prtype, col->m_col.mbminmaxlen, max_prefix, field->len, | |
| 25708 |
2/4✓ Branch 0 taken 7372 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7372 times.
✗ Branch 3 not taken.
|
7372 | static_cast<char *>(dfield_get_data(field))); |
| 25709 |
1/2✓ Branch 0 taken 7372 times.
✗ Branch 1 not taken.
|
7372 | dfield_set_len(field, len); |
| 25710 | } | ||
| 25711 | |||
| 25712 |
7/8✓ Branch 0 taken 32861 times.
✓ Branch 1 taken 1404 times.
✓ Branch 2 taken 32861 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7534 times.
✓ Branch 5 taken 25327 times.
✓ Branch 6 taken 7534 times.
✓ Branch 7 taken 26731 times.
|
34265 | if (heap != nullptr && !dfield_is_multi_value(field)) { |
| 25713 |
1/2✓ Branch 0 taken 7534 times.
✗ Branch 1 not taken.
|
7534 | dfield_dup(field, heap); |
| 25714 | } | ||
| 25715 | |||
| 25716 | 34265 | return (field); | |
| 25717 | 34420 | } | |
| 25718 | |||
| 25719 | /** Attempt to push down an index condition. | ||
| 25720 | @param[in] keyno MySQL key number | ||
| 25721 | @param[in] idx_cond Index condition to be checked | ||
| 25722 | @return idx_cond if pushed; NULL if not pushed */ | ||
| 25723 | 2538 | class Item *ha_innobase::idx_cond_push(uint keyno, class Item *idx_cond) { | |
| 25724 |
1/2✓ Branch 0 taken 2538 times.
✗ Branch 1 not taken.
|
2538 | DBUG_TRACE; |
| 25725 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2538 times.
|
2538 | assert(keyno != MAX_KEY); |
| 25726 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2538 times.
|
2538 | assert(idx_cond != nullptr); |
| 25727 | |||
| 25728 | 2538 | pushed_idx_cond = idx_cond; | |
| 25729 | 2538 | pushed_idx_cond_keyno = keyno; | |
| 25730 | 2538 | in_range_check_pushed_down = true; | |
| 25731 | /* We will evaluate the condition entirely */ | ||
| 25732 | 2538 | return nullptr; | |
| 25733 | 2538 | } | |
| 25734 | |||
| 25735 | /** Find out if a Record_buffer is wanted by this handler, and what is the | ||
| 25736 | maximum buffer size the handler wants. | ||
| 25737 | |||
| 25738 | @param[out] max_rows gets set to the maximum number of records to allocate | ||
| 25739 | space for in the buffer | ||
| 25740 | @retval true if the handler wants a buffer | ||
| 25741 | @retval false if the handler does not want a buffer */ | ||
| 25742 | 555976 | bool ha_innobase::is_record_buffer_wanted(ha_rows *const max_rows) const { | |
| 25743 | /* If the scan won't be able to utilize the record buffer, return that | ||
| 25744 | we don't want one. The decision on whether to use a buffer is taken in | ||
| 25745 | row_search_mvcc(), look for the comment that starts with "Decide | ||
| 25746 | whether to prefetch extra rows." Let's do the same check here. */ | ||
| 25747 | |||
| 25748 |
2/2✓ Branch 0 taken 374908 times.
✓ Branch 1 taken 181073 times.
|
555976 | if (!m_prebuilt->can_prefetch_records()) { |
| 25749 | 374908 | *max_rows = 0; | |
| 25750 | 374908 | return false; | |
| 25751 | } | ||
| 25752 | |||
| 25753 | /* Limit the number of rows in the buffer to 100 for now. We may want | ||
| 25754 | to fine-tune this later, possibly taking record size and page size into | ||
| 25755 | account. The optimizer might allocate an even smaller buffer if it | ||
| 25756 | thinks a smaller number of rows will be fetched. */ | ||
| 25757 | 181073 | *max_rows = 100; | |
| 25758 | 181073 | return true; | |
| 25759 | } | ||
| 25760 | |||
| 25761 | /** Return max limits for a single set of multi-valued keys | ||
| 25762 | @param[out] num_keys number of keys to store | ||
| 25763 | @param[out] keys_length total length of keys, bytes | ||
| 25764 | */ | ||
| 25765 | 27978 | void ha_innobase::mv_key_capacity(uint *num_keys, size_t *keys_length) const { | |
| 25766 | /* The limit of multi-value should be checked against undo page size, | ||
| 25767 | because a record length can not be longer than an undo page size. | ||
| 25768 | Actually, it should not be longer than half of a page size, but this | ||
| 25769 | can be checked for the full record. | ||
| 25770 | |||
| 25771 | The problem is, even if the number of multi-value fields are known, | ||
| 25772 | the actual number of multiple values per field are not known until | ||
| 25773 | the record itself gets inserted. So it's impossible to estimate the | ||
| 25774 | accurate max number of multiple values. Meanwhile, since other fields | ||
| 25775 | are not known in advance, so it's also impossible to estimate the | ||
| 25776 | accurate total key length. | ||
| 25777 | |||
| 25778 | Therefore, only the best effort can be done in this function. | ||
| 25779 | That is the estimation will be based on the INSERT to the table. | ||
| 25780 | And excluding all must have space, the left length is regarded | ||
| 25781 | as the keys_length. And the number of the keys would be got by | ||
| 25782 | keys_length / min(multi-value fields' length). Note if it is a | ||
| 25783 | variable length field, then it's data length is regarded as 1. | ||
| 25784 | |||
| 25785 | Furthermore, to make the calculation as simple as possible, some | ||
| 25786 | space cost would be ignored. This should not be a big deal, since | ||
| 25787 | the whole estimation is only a rough one. | ||
| 25788 | |||
| 25789 | So it's the greedy estimation which will try to give a most relaxed | ||
| 25790 | restriction on the table, to allow insert and update go as more as | ||
| 25791 | possible. The DB_UNDO_RECORD_TOO_BIG error would be raised if the | ||
| 25792 | actual user record exceeds the undo page size. */ | ||
| 25793 | |||
| 25794 | 27978 | size_t free_space = trx_undo_max_free_space(); | |
| 25795 | |||
| 25796 | /* PK always takes place in log page, take that into account */ | ||
| 25797 | 27978 | uint pk = table->s->primary_key; | |
| 25798 |
2/2✓ Branch 0 taken 17555 times.
✓ Branch 1 taken 10423 times.
|
27978 | if (pk != MAX_KEY) { |
| 25799 | 17555 | free_space -= table->s->key_info[pk].key_length; | |
| 25800 | } else { | ||
| 25801 | /* Deduct default InnoDB's PK length */ | ||
| 25802 | 10423 | free_space -= DATA_ROW_ID_LEN; | |
| 25803 | } | ||
| 25804 | |||
| 25805 | /* Maybe the space for any normal virtual columns etc. should be | ||
| 25806 | considered here, however, no details can be know at this time point, | ||
| 25807 | so just ignore them all */ | ||
| 25808 | |||
| 25809 | /* Find out the minimum key length so to get the maximum number | ||
| 25810 | of keys */ | ||
| 25811 | 27978 | uint16_t min_mv_key_length = std::numeric_limits<uint16_t>::max(); | |
| 25812 | |||
| 25813 |
2/2✓ Branch 0 taken 89128 times.
✓ Branch 1 taken 26575 times.
|
115703 | for (uint16_t i = 0; i < table->s->fields; ++i) { |
| 25814 | 89128 | Field *field = table->field[i]; | |
| 25815 |
2/2✓ Branch 0 taken 60874 times.
✓ Branch 1 taken 28254 times.
|
89128 | if (!innobase_is_multi_value_fld(field)) { |
| 25816 | 60874 | continue; | |
| 25817 | } | ||
| 25818 | |||
| 25819 | /* In case of variable length type, assume the minimum length of data, | ||
| 25820 | to make a maximum estimation of keys and allow users to insert as | ||
| 25821 | many keys as possible, under the constraint of total key length. */ | ||
| 25822 |
2/2✓ Branch 0 taken 1403 times.
✓ Branch 1 taken 26851 times.
|
28254 | if (field->type() == MYSQL_TYPE_VARCHAR) { |
| 25823 | 1403 | min_mv_key_length = 1; | |
| 25824 | 1403 | break; | |
| 25825 | } | ||
| 25826 | |||
| 25827 |
2/2✓ Branch 0 taken 26760 times.
✓ Branch 1 taken 91 times.
|
26851 | if (min_mv_key_length > field->key_length()) { |
| 25828 | 26760 | min_mv_key_length = field->key_length(); | |
| 25829 | } | ||
| 25830 | } | ||
| 25831 | |||
| 25832 | 27978 | *keys_length = Multi_value_logger::get_keys_capacity( | |
| 25833 | static_cast<uint32_t>(free_space), min_mv_key_length, num_keys); | ||
| 25834 | 27978 | } | |
| 25835 | |||
| 25836 | /** Use this when the args are passed to the format string from | ||
| 25837 | messages_to_clients.txt directly as is. | ||
| 25838 | |||
| 25839 | Push a warning message to the client, it is a wrapper around: | ||
| 25840 | |||
| 25841 | void push_warning_printf( | ||
| 25842 | THD *thd, Sql_condition::enum_condition_level level, | ||
| 25843 | uint code, const char *format, ...); | ||
| 25844 | */ | ||
| 25845 | 3042 | void ib_senderrf(THD *thd, /*!< in/out: session */ | |
| 25846 | ib_log_level_t level, /*!< in: warning level */ | ||
| 25847 | uint32_t code, /*!< MySQL error code */ | ||
| 25848 | ...) /*!< Args */ | ||
| 25849 | { | ||
| 25850 | va_list args; | ||
| 25851 | 3042 | char *str = nullptr; | |
| 25852 |
1/2✓ Branch 0 taken 3042 times.
✗ Branch 1 not taken.
|
3042 | const char *format = innobase_get_err_msg(code); |
| 25853 | |||
| 25854 | /* If the caller wants to push a message to the client then | ||
| 25855 | the caller must pass a valid session handle. */ | ||
| 25856 | |||
| 25857 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
|
3042 | ut_a(thd != nullptr); |
| 25858 | |||
| 25859 | /* The error code must exist in the messages_to_clients.txt file. */ | ||
| 25860 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
|
3042 | ut_a(format != nullptr); |
| 25861 | |||
| 25862 | 3042 | va_start(args, code); | |
| 25863 | |||
| 25864 | #ifdef _WIN32 | ||
| 25865 | int size = _vscprintf(format, args) + 1; | ||
| 25866 | if (size > 0) { | ||
| 25867 | str = static_cast<char *>(malloc(size)); | ||
| 25868 | } | ||
| 25869 | if (str == NULL) { | ||
| 25870 | va_end(args); | ||
| 25871 | return; /* Watch for Out-Of-Memory */ | ||
| 25872 | } | ||
| 25873 | str[size - 1] = 0x0; | ||
| 25874 | vsnprintf(str, size, format, args); | ||
| 25875 | #elif HAVE_VASPRINTF | ||
| 25876 | int ret; | ||
| 25877 | 3042 | ret = vasprintf(&str, format, args); | |
| 25878 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
|
3042 | if (ret < 0) { |
| 25879 | ✗ | va_end(args); | |
| 25880 | ✗ | return; /* Watch for Out-Of-Memory */ | |
| 25881 | } | ||
| 25882 | #else | ||
| 25883 | /* Use a fixed length string. */ | ||
| 25884 | str = static_cast<char *>(malloc(BUFSIZ)); | ||
| 25885 | if (str == NULL) { | ||
| 25886 | va_end(args); | ||
| 25887 | return; /* Watch for Out-Of-Memory */ | ||
| 25888 | } | ||
| 25889 | vsnprintf(str, BUFSIZ, format, args); | ||
| 25890 | #endif /* _WIN32 */ | ||
| 25891 | |||
| 25892 | Sql_condition::enum_severity_level l; | ||
| 25893 | |||
| 25894 | 3042 | l = Sql_condition::SL_NOTE; | |
| 25895 | |||
| 25896 |
2/5✗ Branch 0 not taken.
✓ Branch 1 taken 2380 times.
✓ Branch 2 taken 662 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
3042 | switch (level) { |
| 25897 | ✗ | case IB_LOG_LEVEL_INFO: | |
| 25898 | ✗ | break; | |
| 25899 | 2380 | case IB_LOG_LEVEL_WARN: | |
| 25900 | 2380 | l = Sql_condition::SL_WARNING; | |
| 25901 | 2380 | break; | |
| 25902 | 662 | case IB_LOG_LEVEL_ERROR: | |
| 25903 | /* We can't use push_warning_printf(), it is a hard error. */ | ||
| 25904 |
1/2✓ Branch 0 taken 662 times.
✗ Branch 1 not taken.
|
662 | my_printf_error(code, "%s", MYF(0), str); |
| 25905 | 662 | break; | |
| 25906 | ✗ | case IB_LOG_LEVEL_FATAL: | |
| 25907 | ✗ | l = Sql_condition::SEVERITY_END; | |
| 25908 | ✗ | break; | |
| 25909 | #ifdef UNIV_HOTBACKUP | ||
| 25910 | default: | ||
| 25911 | break; | ||
| 25912 | #endif /* UNIV_HOTBACKUP */ | ||
| 25913 | } | ||
| 25914 | |||
| 25915 |
2/2✓ Branch 0 taken 2380 times.
✓ Branch 1 taken 662 times.
|
3042 | if (level != IB_LOG_LEVEL_ERROR) { |
| 25916 |
1/2✓ Branch 0 taken 2380 times.
✗ Branch 1 not taken.
|
2380 | push_warning_printf(thd, l, code, "InnoDB: %s", str); |
| 25917 | } | ||
| 25918 | |||
| 25919 | 3042 | va_end(args); | |
| 25920 | 3042 | free(str); | |
| 25921 | |||
| 25922 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3042 times.
|
3042 | if (level == IB_LOG_LEVEL_FATAL) { |
| 25923 | ✗ | ut_error; | |
| 25924 | } | ||
| 25925 | } | ||
| 25926 | |||
| 25927 | /** Use this when the args are first converted to a formatted string and then | ||
| 25928 | passed to the format string from messages_to_clients.txt. The error message | ||
| 25929 | format must be: "Some string ... %s". | ||
| 25930 | |||
| 25931 | Push a warning message to the client, it is a wrapper around: | ||
| 25932 | |||
| 25933 | void push_warning_printf( | ||
| 25934 | THD *thd, Sql_condition::enum_condition_level level, | ||
| 25935 | uint code, const char *format, ...); | ||
| 25936 | */ | ||
| 25937 | 378 | void ib_errf(THD *thd, /*!< in/out: session */ | |
| 25938 | ib_log_level_t level, /*!< in: warning level */ | ||
| 25939 | uint32_t code, /*!< MySQL error code */ | ||
| 25940 | const char *format, /*!< printf format */ | ||
| 25941 | ...) /*!< Args */ | ||
| 25942 | { | ||
| 25943 | 378 | char *str = nullptr; | |
| 25944 | va_list args; | ||
| 25945 | |||
| 25946 | /* If the caller wants to push a message to the client then | ||
| 25947 | the caller must pass a valid session handle. */ | ||
| 25948 | |||
| 25949 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
|
378 | ut_a(thd != nullptr); |
| 25950 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
|
378 | ut_a(format != nullptr); |
| 25951 | |||
| 25952 | 378 | va_start(args, format); | |
| 25953 | |||
| 25954 | #ifdef _WIN32 | ||
| 25955 | int size = _vscprintf(format, args) + 1; | ||
| 25956 | if (size > 0) { | ||
| 25957 | str = static_cast<char *>(malloc(size)); | ||
| 25958 | } | ||
| 25959 | if (str == NULL) { | ||
| 25960 | va_end(args); | ||
| 25961 | return; /* Watch for Out-Of-Memory */ | ||
| 25962 | } | ||
| 25963 | str[size - 1] = 0x0; | ||
| 25964 | vsnprintf(str, size, format, args); | ||
| 25965 | #elif HAVE_VASPRINTF | ||
| 25966 | int ret; | ||
| 25967 | 378 | ret = vasprintf(&str, format, args); | |
| 25968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 378 times.
|
378 | if (ret < 0) { |
| 25969 | ✗ | va_end(args); | |
| 25970 | ✗ | return; /* Watch for Out-Of-Memory */ | |
| 25971 | } | ||
| 25972 | #else | ||
| 25973 | /* Use a fixed length string. */ | ||
| 25974 | str = static_cast<char *>(malloc(BUFSIZ)); | ||
| 25975 | if (str == NULL) { | ||
| 25976 | va_end(args); | ||
| 25977 | return; /* Watch for Out-Of-Memory */ | ||
| 25978 | } | ||
| 25979 | vsnprintf(str, BUFSIZ, format, args); | ||
| 25980 | #endif /* _WIN32 */ | ||
| 25981 | |||
| 25982 |
1/2✓ Branch 0 taken 378 times.
✗ Branch 1 not taken.
|
378 | ib_senderrf(thd, level, code, str); |
| 25983 | |||
| 25984 | 378 | va_end(args); | |
| 25985 | 378 | free(str); | |
| 25986 | } | ||
| 25987 | #endif /* !UNIV_HOTBACKUP */ | ||
| 25988 | |||
| 25989 | /* Keep the first 16 characters as-is, since the url is sometimes used | ||
| 25990 | as an offset from this.*/ | ||
| 25991 | const char *TROUBLESHOOTING_MSG = "Please refer to " REFMAN | ||
| 25992 | "innodb-troubleshooting.html" | ||
| 25993 | " for how to resolve the issue."; | ||
| 25994 | |||
| 25995 | const char *TROUBLESHOOT_DATADICT_MSG = "Please refer to " REFMAN | ||
| 25996 | "innodb-troubleshooting-datadict.html" | ||
| 25997 | " for how to resolve the issue."; | ||
| 25998 | |||
| 25999 | const char *BUG_REPORT_MSG = | ||
| 26000 | "Submit a detailed bug report to http://bugs.mysql.com"; | ||
| 26001 | |||
| 26002 | const char *FORCE_RECOVERY_MSG = "Please refer to " REFMAN | ||
| 26003 | "forcing-innodb-recovery.html" | ||
| 26004 | " for information about forcing recovery."; | ||
| 26005 | |||
| 26006 | const char *ERROR_CREATING_MSG = | ||
| 26007 | "Please refer to " REFMAN "error-creating-innodb.html"; | ||
| 26008 | |||
| 26009 | const char *OPERATING_SYSTEM_ERROR_MSG = | ||
| 26010 | "Refer to your operating system documentation for operating" | ||
| 26011 | " system error code information."; | ||
| 26012 | |||
| 26013 | const char *FOREIGN_KEY_CONSTRAINTS_MSG = | ||
| 26014 | "Please refer to " REFMAN | ||
| 26015 | "create-table-foreign-keys.html" | ||
| 26016 | " for correct foreign key definition."; | ||
| 26017 | |||
| 26018 | const char *INNODB_PARAMETERS_MSG = | ||
| 26019 | "Please refer to " REFMAN "innodb-parameters.html"; | ||
| 26020 | |||
| 26021 | #ifndef UNIV_HOTBACKUP | ||
| 26022 | /********************************************************************** | ||
| 26023 | Converts an identifier from my_charset_filename to UTF-8 charset. | ||
| 26024 | @return result string length, as returned by strconvert() */ | ||
| 26025 | 453 | uint innobase_convert_to_filename_charset( | |
| 26026 | char *to, /* out: converted identifier */ | ||
| 26027 | const char *from, /* in: identifier to convert */ | ||
| 26028 | ulint len) /* in: length of 'to', in bytes */ | ||
| 26029 | { | ||
| 26030 | uint errors; | ||
| 26031 | 453 | CHARSET_INFO *cs_to = &my_charset_filename; | |
| 26032 | 453 | CHARSET_INFO *cs_from = system_charset_info; | |
| 26033 | |||
| 26034 | return (static_cast<uint>( | ||
| 26035 |
1/2✓ Branch 0 taken 453 times.
✗ Branch 1 not taken.
|
453 | strconvert(cs_from, from, cs_to, to, static_cast<size_t>(len), &errors))); |
| 26036 | } | ||
| 26037 | |||
| 26038 | /********************************************************************** | ||
| 26039 | Converts an identifier from my_charset_filename to UTF-8 charset. | ||
| 26040 | @return result string length, as returned by strconvert() */ | ||
| 26041 | 49 | uint innobase_convert_to_system_charset( | |
| 26042 | char *to, /* out: converted identifier */ | ||
| 26043 | const char *from, /* in: identifier to convert */ | ||
| 26044 | ulint len, /* in: length of 'to', in bytes */ | ||
| 26045 | uint *errors) /* out: error return */ | ||
| 26046 | { | ||
| 26047 | 49 | CHARSET_INFO *cs1 = &my_charset_filename; | |
| 26048 | 49 | CHARSET_INFO *cs2 = system_charset_info; | |
| 26049 | |||
| 26050 | return (static_cast<uint>( | ||
| 26051 | 49 | strconvert(cs1, from, cs2, to, static_cast<size_t>(len), errors))); | |
| 26052 | } | ||
| 26053 | |||
| 26054 | /********************************************************************** | ||
| 26055 | Issue a warning that the row is too big. */ | ||
| 26056 | 41 | void ib_warn_row_too_big(const dict_table_t *table) { | |
| 26057 | /* If prefix is true then a 768-byte prefix is stored | ||
| 26058 | locally for BLOB fields. */ | ||
| 26059 | 41 | const bool prefix = !dict_table_has_atomic_blobs(table); | |
| 26060 | |||
| 26061 | const ulint free_space = | ||
| 26062 | 41 | page_get_free_space_of_empty(table->flags & DICT_TF_COMPACT) / 2; | |
| 26063 | |||
| 26064 | 41 | THD *thd = current_thd; | |
| 26065 | |||
| 26066 |
4/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 21 times.
|
41 | push_warning_printf( |
| 26067 | thd, Sql_condition::SL_WARNING, HA_ERR_TOO_BIG_ROW, | ||
| 26068 | "Row size too large (> %lu). Changing some columns to TEXT" | ||
| 26069 | " or BLOB %smay help. In current row format, BLOB prefix of" | ||
| 26070 | " %d bytes is stored inline.", | ||
| 26071 | free_space, | ||
| 26072 | prefix ? "or using ROW_FORMAT=DYNAMIC or" | ||
| 26073 | " ROW_FORMAT=COMPRESSED " | ||
| 26074 | : "", | ||
| 26075 | prefix ? DICT_MAX_FIXED_COL_LEN : 0); | ||
| 26076 | 41 | } | |
| 26077 | |||
| 26078 | /** Constructs fake dict_col_t describing column for foreign key type | ||
| 26079 | compatibility check from column description in Ha_fk_column_type form. | ||
| 26080 | |||
| 26081 | @note dict_col_t which is produced by this call is not valid for general | ||
| 26082 | purposes. | ||
| 26083 | @param[out] col dict_col_t filled by this function | ||
| 26084 | @param[in] fk_col_type foreign key type information */ | ||
| 26085 | 678106 | static void innodb_fill_fake_column_struct( | |
| 26086 | dict_col_t *col, const Ha_fk_column_type *fk_col_type) { | ||
| 26087 | ulint unsigned_type; | ||
| 26088 | ulint binary_type; | ||
| 26089 | ulint charset_no; | ||
| 26090 | |||
| 26091 | 1356212 | ulint mtype = get_innobase_type_from_mysql_dd_type( | |
| 26092 | 678106 | &unsigned_type, &binary_type, &charset_no, fk_col_type->type, | |
| 26093 |
1/2✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
|
678106 | fk_col_type->field_charset, fk_col_type->is_unsigned); |
| 26094 | |||
| 26095 | /* Fake prtype only contains info which is relevant for foreign key | ||
| 26096 | type compatibility check, especially the info used in cmp_cols_are_equal. */ | ||
| 26097 | ulint fake_prtype = | ||
| 26098 |
1/2✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
|
678106 | dtype_form_prtype(unsigned_type | binary_type, charset_no); |
| 26099 | |||
| 26100 | 1356212 | ulint col_len = calc_pack_length( | |
| 26101 | 678106 | fk_col_type->type, fk_col_type->char_length, fk_col_type->elements_count, | |
| 26102 | /* InnoDB always treats BIT as char. */ | ||
| 26103 |
1/2✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
|
678106 | true, fk_col_type->numeric_scale, fk_col_type->is_unsigned); |
| 26104 | |||
| 26105 |
1/2✓ Branch 0 taken 678106 times.
✗ Branch 1 not taken.
|
678106 | dict_mem_fill_column_struct(col, 0 /* fake col_pos */, mtype, fake_prtype, |
| 26106 | col_len, true, UINT32_UNDEFINED, 0, 0); | ||
| 26107 | 678106 | } | |
| 26108 | |||
| 26109 | /** Check if types of child and parent columns in foreign key are compatible. | ||
| 26110 | |||
| 26111 | @param[in] child_column_type Child column type description. | ||
| 26112 | @param[in] parent_column_type Parent column type description. | ||
| 26113 | @param[in] check_charsets Indicates whether we need to check | ||
| 26114 | that charsets of string columns | ||
| 26115 | match. Which is true in most cases. | ||
| 26116 | |||
| 26117 | @return True if types are compatible, False if not. */ | ||
| 26118 | 339053 | static bool innodb_check_fk_column_compat( | |
| 26119 | const Ha_fk_column_type *child_column_type, | ||
| 26120 | const Ha_fk_column_type *parent_column_type, bool check_charsets) { | ||
| 26121 | 339053 | dict_col_t dict_child_col, dict_parent_col; | |
| 26122 | |||
| 26123 |
1/2✓ Branch 0 taken 339053 times.
✗ Branch 1 not taken.
|
339053 | innodb_fill_fake_column_struct(&dict_child_col, child_column_type); |
| 26124 |
1/2✓ Branch 0 taken 339053 times.
✗ Branch 1 not taken.
|
339053 | innodb_fill_fake_column_struct(&dict_parent_col, parent_column_type); |
| 26125 | |||
| 26126 | return ( | ||
| 26127 |
1/2✓ Branch 0 taken 339053 times.
✗ Branch 1 not taken.
|
678106 | cmp_cols_are_equal(&dict_child_col, &dict_parent_col, check_charsets)); |
| 26128 | } | ||
| 26129 | |||
| 26130 | 18536 | static bool innobase_check_reserved_file_name(handlerton *, const char *name) { | |
| 26131 | 18536 | CHARSET_INFO *ci = system_charset_info; | |
| 26132 | 18536 | size_t logname_size = strlen(log_pre_8_0_30::FILE_BASE_NAME); | |
| 26133 | |||
| 26134 | /* Name is smaller than reserved name */ | ||
| 26135 |
2/2✓ Branch 0 taken 17177 times.
✓ Branch 1 taken 1359 times.
|
18536 | if (strlen(name) < logname_size) { |
| 26136 | 17177 | return (false); | |
| 26137 | } | ||
| 26138 | /* Do case insensitive comparison for name. */ | ||
| 26139 |
1/2✓ Branch 0 taken 1405 times.
✗ Branch 1 not taken.
|
1405 | for (uint i = 0; i < logname_size; i++) { |
| 26140 |
3/6✓ Branch 0 taken 1405 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1405 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1405 times.
|
1405 | ut_ad(!my_isalpha(ci, log_pre_8_0_30::FILE_BASE_NAME[i]) || |
| 26141 | my_islower(ci, log_pre_8_0_30::FILE_BASE_NAME[i])); | ||
| 26142 | |||
| 26143 |
2/2✓ Branch 0 taken 1359 times.
✓ Branch 1 taken 46 times.
|
1405 | if (my_tolower(ci, name[i]) != log_pre_8_0_30::FILE_BASE_NAME[i]) { |
| 26144 | 1359 | return (false); | |
| 26145 | } | ||
| 26146 | } | ||
| 26147 | ✗ | return (true); | |
| 26148 | } | ||
| 26149 | #endif /* !UNIV_HOTBACKUP */ | ||
| 26150 |